Merge branch 'develop' of github.com:Budibase/budibase into fix/BUDI-6754

This commit is contained in:
mike12345567 2023-04-05 17:59:18 +01:00
commit 0803b08217
194 changed files with 3626 additions and 3701 deletions

View File

@ -77,28 +77,21 @@ jobs:
- run: yarn bootstrap
- run: yarn test:pro
# integration-test:
# runs-on: ubuntu-latest
# services:
# couchdb:
# image: ibmcom/couchdb3
# env:
# COUCHDB_PASSWORD: budibase
# COUCHDB_USER: budibase
# ports:
# - 4567:5984
# steps:
# - uses: actions/checkout@v2
# - name: Use Node.js 14.x
# uses: actions/setup-node@v1
# with:
# node-version: 14.x
# - name: Install Pro
# run: yarn install:pro $BRANCH $BASE_BRANCH
# - run: yarn
# - run: yarn bootstrap
# - run: yarn build
# - run: |
# cd qa-core
# yarn
# yarn api:test:ci
integration-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 14.x
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Install Pro
run: yarn install:pro $BRANCH $BASE_BRANCH
- run: yarn && yarn bootstrap && yarn build
- run: |
cd qa-core
yarn setup
yarn test:ci
env:
BB_ADMIN_USER_EMAIL: admin
BB_ADMIN_USER_PASSWORD: admin

View File

@ -64,6 +64,8 @@ spec:
value: {{ .Values.globals.enableAnalytics | quote }}
- name: API_ENCRYPTION_KEY
value: {{ .Values.globals.apiEncryptionKey | quote }}
- name: HTTP_LOGGING
value: {{ .Values.services.apps.httpLogging | quote }}
- name: INTERNAL_API_KEY
valueFrom:
secretKeyRef:
@ -119,7 +121,7 @@ spec:
- name: MULTI_TENANCY
value: {{ .Values.globals.multiTenancy | quote }}
- name: LOG_LEVEL
value: {{ default "info" .Values.services.apps.logLevel | quote }}
value: {{ .Values.services.apps.logLevel | quote }}
- name: REDIS_PASSWORD
value: {{ .Values.services.redis.password }}
- name: REDIS_URL
@ -180,18 +182,6 @@ spec:
- name: DD_APM_DD_URL
value: https://trace.agent.datadoghq.eu
{{ end }}
{{ if .Values.globals.elasticApmEnabled }}
- name: ELASTIC_APM_ENABLED
value: {{ .Values.globals.elasticApmEnabled | quote }}
{{ end }}
{{ if .Values.globals.elasticApmSecretToken }}
- name: ELASTIC_APM_SECRET_TOKEN
value: {{ .Values.globals.elasticApmSecretToken | quote }}
{{ end }}
{{ if .Values.globals.elasticApmServerUrl }}
- name: ELASTIC_APM_SERVER_URL
value: {{ .Values.globals.elasticApmServerUrl | quote }}
{{ end }}
{{ if .Values.globals.globalAgentHttpProxy }}
- name: GLOBAL_AGENT_HTTP_PROXY
value: {{ .Values.globals.globalAgentHttpProxy | quote }}

View File

@ -64,6 +64,8 @@ spec:
{{ end }}
- name: API_ENCRYPTION_KEY
value: {{ .Values.globals.apiEncryptionKey | quote }}
- name: HTTP_LOGGING
value: {{ .Values.services.worker.httpLogging | quote }}
- name: INTERNAL_API_KEY
valueFrom:
secretKeyRef:
@ -115,7 +117,7 @@ spec:
- name: MULTI_TENANCY
value: {{ .Values.globals.multiTenancy | quote }}
- name: LOG_LEVEL
value: {{ default "info" .Values.services.worker.logLevel | quote }}
value: {{ .Values.services.worker.logLevel | quote }}
- name: REDIS_PASSWORD
value: {{ .Values.services.redis.password | quote }}
- name: REDIS_URL
@ -170,18 +172,6 @@ spec:
- name: DD_APM_DD_URL
value: https://trace.agent.datadoghq.eu
{{ end }}
{{ if .Values.globals.elasticApmEnabled }}
- name: ELASTIC_APM_ENABLED
value: {{ .Values.globals.elasticApmEnabled | quote }}
{{ end }}
{{ if .Values.globals.elasticApmSecretToken }}
- name: ELASTIC_APM_SECRET_TOKEN
value: {{ .Values.globals.elasticApmSecretToken | quote }}
{{ end }}
{{ if .Values.globals.elasticApmServerUrl }}
- name: ELASTIC_APM_SERVER_URL
value: {{ .Values.globals.elasticApmServerUrl | quote }}
{{ end }}
{{ if .Values.globals.globalAgentHttpProxy }}
- name: GLOBAL_AGENT_HTTP_PROXY
value: {{ .Values.globals.globalAgentHttpProxy | quote }}

View File

@ -80,7 +80,6 @@ globals:
enableAnalytics: "1"
sentryDSN: ""
posthogToken: "phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU"
logLevel: info
selfHosted: "1" # set to 0 for budibase cloud environment, set to 1 for self-hosted setup
multiTenancy: "0" # set to 0 to disable multiple orgs, set to 1 to enable multiple orgs
accountPortalUrl: ""
@ -107,9 +106,6 @@ globals:
smtp:
enabled: false
# elasticApmEnabled:
# elasticApmSecretToken:
# elasticApmServerUrl:
# globalAgentHttpProxy:
# globalAgentHttpsProxy:
# globalAgentNoProxy:
@ -137,6 +133,7 @@ services:
port: 4002
replicaCount: 1
logLevel: info
httpLogging: 1
resources: {}
# nodeDebug: "" # set the value of NODE_DEBUG
# annotations:
@ -147,6 +144,8 @@ services:
worker:
port: 4003
replicaCount: 1
logLevel: info
httpLogging: 1
resources: {}
# annotations:
# co.elastic.logs/multiline.type: pattern

View File

@ -1,5 +1,5 @@
{
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"npmClient": "yarn",
"packages": ["packages/*"],
"command": {

View File

@ -23,10 +23,12 @@
},
"scripts": {
"setup": "node ./hosting/scripts/setup.js && yarn && yarn bootstrap && yarn build && yarn dev",
"bootstrap": "lerna bootstrap && lerna link && ./scripts/link-dependencies.sh",
"bootstrap": "lerna bootstrap",
"postbootstrap": "lerna link && ./scripts/link-dependencies.sh",
"build": "lerna run --stream build",
"build:dev": "lerna run --stream prebuild && tsc --build --watch --preserveWatchOutput",
"build:backend": "lerna run --stream build --ignore @budibase/client --ignore @budibase/bbui --ignore @budibase/builder --ignore @budibase/cli",
"backend:bootstrap": "./scripts/scopeBackend.sh 'lerna bootstrap' && yarn run postbootstrap",
"backend:build": "./scripts/scopeBackend.sh 'lerna run --stream build'",
"build:sdk": "lerna run --stream build:sdk",
"deps:circular": "madge packages/server/dist/index.js packages/worker/src/index.ts packages/backend-core/dist/src/index.js packages/cli/src/index.js --circular",
"release": "lerna publish ${RELEASE_VERSION_TYPE:-patch} --yes --force-publish && yarn release:pro",
@ -44,6 +46,7 @@
"dev": "yarn run kill-all && lerna link && lerna run --stream --parallel dev:builder --concurrency 1 --stream",
"dev:noserver": "yarn run kill-builder && lerna link && lerna run --stream dev:stack:up && lerna run --stream --parallel dev:builder --concurrency 1 --ignore @budibase/backend-core --ignore @budibase/server --ignore @budibase/worker",
"dev:server": "yarn run kill-server && lerna run --stream --parallel dev:builder --concurrency 1 --scope @budibase/backend-core --scope @budibase/worker --scope @budibase/server",
"dev:built": "cd packages/server && yarn dev:stack:up && cd ../../ && lerna run --stream --parallel dev:built",
"test": "lerna run --stream test --stream",
"test:pro": "bash scripts/pro/test.sh",
"lint:eslint": "eslint packages && eslint qa-core",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/backend-core",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Budibase backend core libraries used in server and worker",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
@ -24,7 +24,7 @@
"dependencies": {
"@budibase/nano": "10.1.2",
"@budibase/pouchdb-replication-stream": "1.2.10",
"@budibase/types": "2.4.44-alpha.5",
"@budibase/types": "2.4.44-alpha.9",
"@shopify/jest-koa-mocks": "5.0.1",
"@techpass/passport-openidconnect": "0.3.2",
"aws-cloudfront-sign": "2.2.0",
@ -39,6 +39,7 @@
"joi": "17.6.0",
"jsonwebtoken": "9.0.0",
"koa-passport": "4.1.4",
"koa-pino-logger": "4.0.0",
"lodash": "4.17.21",
"lodash.isarguments": "3.1.0",
"node-fetch": "2.6.7",
@ -64,11 +65,9 @@
"@types/ioredis": "4.28.0",
"@types/jest": "28.1.1",
"@types/koa": "2.13.4",
"@types/koa-pino-logger": "3.0.0",
"@types/lodash": "4.14.180",
"@types/node": "14.18.20",
"@types/node-fetch": "2.6.1",
"@types/pino-http": "5.8.1",
"@types/pouchdb": "6.4.0",
"@types/redlock": "4.0.3",
"@types/semver": "7.3.7",
@ -80,6 +79,7 @@
"jest-serial-runner": "^1.2.1",
"koa": "2.13.4",
"nodemon": "2.0.16",
"pino-pretty": "10.0.0",
"pouchdb-adapter-memory": "7.2.2",
"timekeeper": "2.2.0",
"ts-jest": "28.0.4",

View File

@ -2,6 +2,7 @@ import {
structures,
DBTestConfiguration,
expectFunctionWasCalledTimesWith,
mocks,
} from "../../../tests"
import { Writethrough } from "../writethrough"
import { getDB } from "../../db"
@ -77,9 +78,9 @@ describe("writethrough", () => {
expect.arrayContaining([current._rev, current._rev, newRev])
)
expectFunctionWasCalledTimesWith(
console.warn,
mocks.alerts.logWarn,
2,
"bb-warn: Ignoring redlock conflict in write-through cache"
"Ignoring redlock conflict in write-through cache"
)
const output = await db.get(current._id)

View File

@ -36,6 +36,15 @@ function getAPIEncryptionKey() {
: process.env.JWT_SECRET // fallback to the JWT_SECRET used historically
}
function httpLogging() {
if (process.env.HTTP_LOGGING === undefined) {
// on by default unless otherwise specified
return true
}
return process.env.HTTP_LOGGING
}
const environment = {
isTest,
isJest,
@ -90,11 +99,11 @@ const environment = {
USE_COUCH: process.env.USE_COUCH || true,
DEFAULT_LICENSE: process.env.DEFAULT_LICENSE,
SERVICE: process.env.SERVICE || "budibase",
LOG_LEVEL: process.env.LOG_LEVEL,
LOG_LEVEL: process.env.LOG_LEVEL || "info",
SESSION_UPDATE_PERIOD: process.env.SESSION_UPDATE_PERIOD,
DEPLOYMENT_ENVIRONMENT:
process.env.DEPLOYMENT_ENVIRONMENT || "docker-compose",
ENABLE_4XX_HTTP_LOGGING: process.env.ENABLE_4XX_HTTP_LOGGING || true,
HTTP_LOGGING: httpLogging(),
ENABLE_AUDIT_LOG_IP_ADDR: process.env.ENABLE_AUDIT_LOG_IP_ADDR,
// smtp
SMTP_FALLBACK_ENABLED: process.env.SMTP_FALLBACK_ENABLED,

View File

@ -2,14 +2,6 @@ import { Event, Identity, Group } from "@budibase/types"
import { EventProcessor } from "./types"
import env from "../../environment"
const getTimestampString = (timestamp?: string | number) => {
let timestampString = ""
if (timestamp) {
timestampString = `[timestamp=${new Date(timestamp).toISOString()}]`
}
return timestampString
}
const skipLogging = env.SELF_HOSTED && !env.isDev()
export default class LoggingProcessor implements EventProcessor {
@ -22,32 +14,21 @@ export default class LoggingProcessor implements EventProcessor {
if (skipLogging) {
return
}
let timestampString = getTimestampString(timestamp)
let message = `[audit] [identityType=${identity.type}] ${timestampString} ${event} `
if (env.isDev()) {
message = message + `[debug: [properties=${JSON.stringify(properties)}] ]`
}
console.log(message)
console.log(`[audit] [identityType=${identity.type}] ${event}`, properties)
}
async identify(identity: Identity, timestamp?: string | number) {
if (skipLogging) {
return
}
let timestampString = getTimestampString(timestamp)
console.log(
`[audit] [${JSON.stringify(identity)}] ${timestampString} identified`
)
console.log(`[audit] identified`, identity)
}
async identifyGroup(group: Group, timestamp?: string | number) {
if (skipLogging) {
return
}
let timestampString = getTimestampString(timestamp)
console.log(
`[audit] [${JSON.stringify(group)}] ${timestampString} group identified`
)
console.log(`[audit] group identified`, group)
}
shutdown(): void {

View File

@ -1,60 +0,0 @@
import { Header } from "./constants"
import env from "./environment"
const correlator = require("correlation-id")
import { Options } from "pino-http"
import { IncomingMessage } from "http"
const NonErrors = ["AccountError"]
function isSuppressed(e?: any) {
return e && e["suppressAlert"]
}
export function logAlert(message: string, e?: any) {
if (e && NonErrors.includes(e.name) && isSuppressed(e)) {
return
}
let errorJson = ""
if (e) {
errorJson = ": " + JSON.stringify(e, Object.getOwnPropertyNames(e))
}
console.error(`bb-alert: ${message} ${errorJson}`)
}
export function logAlertWithInfo(
message: string,
db: string,
id: string,
error: any
) {
message = `${message} - db: ${db} - doc: ${id} - error: `
logAlert(message, error)
}
export function logWarn(message: string) {
console.warn(`bb-warn: ${message}`)
}
export function pinoSettings(): Options {
return {
prettyPrint: {
levelFirst: true,
},
genReqId: correlator.getId,
level: env.LOG_LEVEL || "error",
autoLogging: {
ignore: (req: IncomingMessage) => !!req.url?.includes("/health"),
},
}
}
const setCorrelationHeader = (headers: any) => {
const correlationId = correlator.getId()
if (correlationId) {
headers[Header.CORRELATION_ID] = correlationId
}
}
export const correlation = {
setHeader: setCorrelationHeader,
}

View File

@ -0,0 +1,26 @@
const NonErrors = ["AccountError"]
function isSuppressed(e?: any) {
return e && e["suppressAlert"]
}
export function logAlert(message: string, e?: any) {
if (e && NonErrors.includes(e.name) && isSuppressed(e)) {
return
}
console.error(`bb-alert: ${message}`, e)
}
export function logAlertWithInfo(
message: string,
db: string,
id: string,
error: any
) {
message = `${message} - db: ${db} - doc: ${id} - error: `
logAlert(message, error)
}
export function logWarn(message: string) {
console.warn(`bb-warn: ${message}`)
}

View File

@ -0,0 +1,13 @@
import { Header } from "../../constants"
const correlator = require("correlation-id")
export const setHeader = (headers: any) => {
const correlationId = correlator.getId()
if (correlationId) {
headers[Header.CORRELATION_ID] = correlationId
}
}
export function getId() {
return correlator.getId()
}

View File

@ -0,0 +1 @@
export * from "./correlation"

View File

@ -0,0 +1,17 @@
import { Header } from "../../constants"
import { v4 as uuid } from "uuid"
const correlator = require("correlation-id")
const correlation = (ctx: any, next: any) => {
// use the provided correlation id header if present
let correlationId = ctx.headers[Header.CORRELATION_ID]
if (!correlationId) {
correlationId = uuid()
}
return correlator.withId(correlationId, () => {
return next()
})
}
export default correlation

View File

@ -0,0 +1,6 @@
export * as correlation from "./correlation/correlation"
export { default as logger } from "./pino/logger"
export * from "./alerts"
// turn off or on context logging i.e. tenantId, appId etc
export let LOG_CONTEXT = true

View File

@ -0,0 +1,170 @@
import env from "../../environment"
import pino, { LoggerOptions } from "pino"
import * as context from "../../context"
import * as correlation from "../correlation"
import { IdentityType } from "@budibase/types"
import { LOG_CONTEXT } from "../index"
// LOGGER
const pinoOptions: LoggerOptions = {
level: env.LOG_LEVEL,
formatters: {
level: label => {
return { level: label.toUpperCase() }
},
bindings: () => {
return {}
},
},
timestamp: () => `,"timestamp":"${new Date(Date.now()).toISOString()}"`,
}
if (env.isDev()) {
pinoOptions.transport = {
target: "pino-pretty",
options: {
singleLine: true,
},
}
}
export const logger = pino(pinoOptions)
// CONSOLE OVERRIDES
interface MergingObject {
objects?: any[]
tenantId?: string
appId?: string
identityId?: string
identityType?: IdentityType
correlationId?: string
err?: Error
}
function isPlainObject(obj: any) {
return typeof obj === "object" && obj !== null && !(obj instanceof Error)
}
function isError(obj: any) {
return obj instanceof Error
}
function isMessage(obj: any) {
return typeof obj === "string"
}
/**
* Backwards compatibility between console logging statements
* and pino logging requirements.
*/
function getLogParams(args: any[]): [MergingObject, string] {
let error = undefined
let objects: any[] = []
let message = ""
args.forEach(arg => {
if (isMessage(arg)) {
message = `${message} ${arg}`.trimStart()
}
if (isPlainObject(arg)) {
objects.push(arg)
}
if (isError(arg)) {
error = arg
}
})
const identity = getIdentity()
let contextObject = {}
if (LOG_CONTEXT) {
contextObject = {
tenantId: getTenantId(),
appId: getAppId(),
identityId: identity?._id,
identityType: identity?.type,
correlationId: correlation.getId(),
}
}
const mergingObject = {
objects: objects.length ? objects : undefined,
err: error,
...contextObject,
}
return [mergingObject, message]
}
console.log = (...arg: any[]) => {
const [obj, msg] = getLogParams(arg)
logger.info(obj, msg)
}
console.info = (...arg: any[]) => {
const [obj, msg] = getLogParams(arg)
logger.info(obj, msg)
}
console.warn = (...arg: any[]) => {
const [obj, msg] = getLogParams(arg)
logger.warn(obj, msg)
}
console.error = (...arg: any[]) => {
const [obj, msg] = getLogParams(arg)
logger.error(obj, msg)
}
/**
* custom trace impl - this resembles the node trace behaviour rather
* than traditional trace logging
* @param arg
*/
console.trace = (...arg: any[]) => {
const [obj, msg] = getLogParams(arg)
if (!obj.err) {
// to get stack trace
obj.err = new Error()
}
logger.trace(obj, msg)
}
console.debug = (...arg: any) => {
const [obj, msg] = getLogParams(arg)
logger.debug(obj, msg)
}
// CONTEXT
const getTenantId = () => {
let tenantId
try {
tenantId = context.getTenantId()
} catch (e: any) {
// do nothing
}
return tenantId
}
const getAppId = () => {
let appId
try {
appId = context.getAppId()
} catch (e) {
// do nothing
}
return appId
}
const getIdentity = () => {
let identity
try {
identity = context.getIdentity()
} catch (e) {
// do nothing
}
return identity
}
export default logger

View File

@ -0,0 +1,45 @@
import env from "../../environment"
import logger from "./logger"
import { IncomingMessage } from "http"
const pino = require("koa-pino-logger")
import { Options } from "pino-http"
import { Ctx } from "@budibase/types"
const correlator = require("correlation-id")
export function pinoSettings(): Options {
return {
logger,
genReqId: correlator.getId,
autoLogging: {
ignore: (req: IncomingMessage) => !!req.url?.includes("/health"),
},
serializers: {
req: req => {
return {
method: req.method,
url: req.url,
correlationId: req.id,
}
},
res: res => {
return {
status: res.statusCode,
}
},
},
}
}
function getMiddleware() {
if (env.HTTP_LOGGING) {
return pino(pinoSettings())
} else {
return (ctx: Ctx, next: any) => {
return next()
}
}
}
const pinoMiddleware = getMiddleware()
export default pinoMiddleware

View File

@ -1,6 +1,5 @@
import { APIError } from "@budibase/types"
import * as errors from "../errors"
import env from "../environment"
export async function errorHandling(ctx: any, next: any) {
try {
@ -9,9 +8,10 @@ export async function errorHandling(ctx: any, next: any) {
const status = err.status || err.statusCode || 500
ctx.status = status
if (status > 499 || env.ENABLE_4XX_HTTP_LOGGING) {
ctx.log.error(err)
console.trace(err)
if (status >= 400 && status < 500) {
console.warn(err)
} else {
console.error(err)
}
const error = errors.getPublicError(err)

View File

@ -14,7 +14,8 @@ export { default as csrf } from "./csrf"
export { default as adminOnly } from "./adminOnly"
export { default as builderOrAdmin } from "./builderOrAdmin"
export { default as builderOnly } from "./builderOnly"
export { default as logging } from "./logging"
export { default as pino } from "../logging/pino/middleware"
export { default as correlation } from "../logging/correlation/middleware"
export { default as errorHandling } from "./errorHandling"
export { default as querystringToBody } from "./querystringToBody"
export * as joiValidator from "./joi-validator"

View File

@ -1,90 +0,0 @@
const correlator = require("correlation-id")
import { Header } from "../constants"
import { v4 as uuid } from "uuid"
import * as context from "../context"
const debug = console.warn
const trace = console.trace
const log = console.log
const info = console.info
const warn = console.warn
const error = console.error
const getTenantId = () => {
let tenantId
try {
tenantId = context.getTenantId()
} catch (e: any) {
// do nothing
}
return tenantId
}
const getAppId = () => {
let appId
try {
appId = context.getAppId()
} catch (e) {
// do nothing
}
return appId
}
const getIdentityId = () => {
let identityId
try {
const identity = context.getIdentity()
identityId = identity?._id
} catch (e) {
// do nothing
}
return identityId
}
const print = (fn: any, data: any[]) => {
let message = ""
const correlationId = correlator.getId()
if (correlationId) {
message = message + `[correlationId=${correlator.getId()}]`
}
const tenantId = getTenantId()
if (tenantId) {
message = message + ` [tenantId=${tenantId}]`
}
const appId = getAppId()
if (appId) {
message = message + ` [appId=${appId}]`
}
const identityId = getIdentityId()
if (identityId) {
message = message + ` [identityId=${identityId}]`
}
if (!process.env.CI) {
fn(message, data)
}
}
const logging = (ctx: any, next: any) => {
// use the provided correlation id header if present
let correlationId = ctx.headers[Header.CORRELATION_ID]
if (!correlationId) {
correlationId = uuid()
}
return correlator.withId(correlationId, () => {
console.debug = data => print(debug, data)
console.trace = data => print(trace, data)
console.log = data => print(log, data)
console.info = data => print(info, data)
console.warn = data => print(warn, data)
console.error = data => print(error, data)
return next()
})
}
export default logging

View File

@ -99,9 +99,7 @@ export const runMigration = async (
options.force[migrationType] &&
options.force[migrationType].includes(migrationName)
) {
log(
`[Tenant: ${tenantId}] [Migration: ${migrationName}] [DB: ${dbName}] Forcing`
)
log(`[Migration: ${migrationName}] [DB: ${dbName}] Forcing`)
} else {
// no force, exit
return
@ -111,7 +109,7 @@ export const runMigration = async (
// check if the migration is not a no-op
if (!options.noOp) {
log(
`[Tenant: ${tenantId}] [Migration: ${migrationName}] [DB: ${dbName}] Running ${lengthStatement}`
`[Migration: ${migrationName}] [DB: ${dbName}] Running ${lengthStatement}`
)
if (migration.preventRetry) {
@ -131,9 +129,7 @@ export const runMigration = async (
await migration.fn(db)
}
log(
`[Tenant: ${tenantId}] [Migration: ${migrationName}] [DB: ${dbName}] Complete`
)
log(`[Migration: ${migrationName}] [DB: ${dbName}] Complete`)
}
// mark as complete
@ -141,7 +137,7 @@ export const runMigration = async (
await db.put(doc)
} catch (err) {
console.error(
`[Tenant: ${tenantId}] [Migration: ${migrationName}] [DB: ${dbName}] Error: `,
`[Migration: ${migrationName}] [DB: ${dbName}] Error: `,
err
)
throw err

View File

@ -3,5 +3,4 @@ process.env.MULTI_TENANCY = "1"
process.env.NODE_ENV = "jest"
process.env.MOCK_REDIS = "1"
process.env.LOG_LEVEL = process.env.LOG_LEVEL || "error"
process.env.ENABLE_4XX_HTTP_LOGGING = "0"
process.env.REDIS_PASSWORD = "budibase"

View File

@ -1,4 +1,3 @@
import "./logging"
import env from "../src/environment"
import { cleanup } from "../src/timers"
import { mocks, testContainerUtils } from "./utilities"

View File

@ -1,34 +0,0 @@
export enum LogLevel {
TRACE = "trace",
DEBUG = "debug",
INFO = "info",
WARN = "warn",
ERROR = "error",
}
const LOG_INDEX: { [key in LogLevel]: number } = {
[LogLevel.TRACE]: 1,
[LogLevel.DEBUG]: 2,
[LogLevel.INFO]: 3,
[LogLevel.WARN]: 4,
[LogLevel.ERROR]: 5,
}
const setIndex = LOG_INDEX[process.env.LOG_LEVEL as LogLevel]
if (setIndex > LOG_INDEX.trace) {
global.console.trace = jest.fn()
}
if (setIndex > LOG_INDEX.debug) {
global.console.debug = jest.fn()
}
if (setIndex > LOG_INDEX.info) {
global.console.info = jest.fn()
global.console.log = jest.fn()
}
if (setIndex > LOG_INDEX.warn) {
global.console.warn = jest.fn()
}

View File

@ -0,0 +1,3 @@
jest.mock("../../../src/logging/alerts")
import * as _alerts from "../../../src/logging/alerts"
export const alerts = jest.mocked(_alerts)

View File

@ -5,5 +5,6 @@ export const accounts = jest.mocked(_accounts)
export * as date from "./date"
export * as licenses from "./licenses"
export { default as fetch } from "./fetch"
export * from "./alerts"
import "./posthog"
import "./events"

View File

@ -1217,15 +1217,6 @@
dependencies:
"@types/koa" "*"
"@types/koa-pino-logger@3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/koa-pino-logger/-/koa-pino-logger-3.0.0.tgz#275d4b000abc14b1928dc2e9ab476c8296a64b6a"
integrity sha512-sP+12JNX01q+nHpCRqkVIuLjaRemQEfDoFg0evpTnjUEI3jUI2ZrOkhQ5coxn3yVm2tedui/2YhlaPn/XrYNWA==
dependencies:
"@types/koa" "*"
"@types/pino" "*"
"@types/pino-http" "*"
"@types/koa@*", "@types/koa@2.13.4":
version "2.13.4"
resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.4.tgz#10620b3f24a8027ef5cbae88b393d1b31205726b"
@ -1273,44 +1264,6 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.20.tgz#268f028b36eaf51181c3300252f605488c4f0650"
integrity sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA==
"@types/pino-http@*", "@types/pino-http@5.8.1":
version "5.8.1"
resolved "https://registry.yarnpkg.com/@types/pino-http/-/pino-http-5.8.1.tgz#ebb194750ad2f9245c3028b5d2c4e6d64f685ba9"
integrity sha512-A9MW6VCnx5ii7s+Fs5aFIw+aSZcBCpsZ/atpxamu8tTsvWFacxSf2Hrn1Ohn1jkVRB/LiPGOapRXcFawDBnDnA==
dependencies:
"@types/pino" "6.3"
"@types/pino-pretty@*":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/pino-pretty/-/pino-pretty-5.0.0.tgz#aa7a61cfd553b051764acfa0a49872f7a09a1722"
integrity sha512-N1uzqSzioqz8R3AkDbSJwcfDWeI3YMPNapSQQhnB2ISU4NYgUIcAh+hYT5ygqBM+klX4htpEhXMmoJv3J7GrdA==
dependencies:
pino-pretty "*"
"@types/pino-std-serializers@*":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1e28b80b554c8222858e99a4e0fc77fd070e10e8"
integrity sha512-gXfUZx2xIBbFYozGms53fT0nvkacx/+62c8iTxrEqH5PkIGAQvDbXg2774VWOycMPbqn5YJBQ3BMsg4Li3dWbg==
dependencies:
pino-std-serializers "*"
"@types/pino@*":
version "7.0.5"
resolved "https://registry.yarnpkg.com/@types/pino/-/pino-7.0.5.tgz#1c84a81b924a6a9e263dbb581dffdbad7a3c60c4"
integrity sha512-wKoab31pknvILkxAF8ss+v9iNyhw5Iu/0jLtRkUD74cNfOOLJNnqfFKAv0r7wVaTQxRZtWrMpGfShwwBjOcgcg==
dependencies:
pino "*"
"@types/pino@6.3":
version "6.3.12"
resolved "https://registry.yarnpkg.com/@types/pino/-/pino-6.3.12.tgz#4425db6ced806109c3df957100cba9dfcd73c228"
integrity sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw==
dependencies:
"@types/node" "*"
"@types/pino-pretty" "*"
"@types/pino-std-serializers" "*"
sonic-boom "^2.1.0"
"@types/pouchdb-adapter-cordova-sqlite@*":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/pouchdb-adapter-cordova-sqlite/-/pouchdb-adapter-cordova-sqlite-1.0.1.tgz#49e5ee6df7cc0c23196fcb340f43a560e74eb1d6"
@ -2539,6 +2492,16 @@ duplexer3@^0.1.4:
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==
duplexify@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==
dependencies:
end-of-stream "^1.4.1"
inherits "^2.0.3"
readable-stream "^3.1.1"
stream-shift "^1.0.0"
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@ -2728,9 +2691,9 @@ extsprintf@^1.2.0:
integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
fast-copy@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.0.tgz#875ebf33b13948ae012b6e51d33da5e6e7571ab8"
integrity sha512-4HzS+9pQ5Yxtv13Lhs1Z1unMXamBdn5nA4bEi1abYpDNSpSp7ODYQ1KPMF6nTatfEzgH6/zPvXKU1zvHiUjWlA==
version "3.0.1"
resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa"
integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==
fast-deep-equal@^3.1.1:
version "3.1.3"
@ -2742,7 +2705,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-redact@^3.1.1:
fast-redact@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa"
integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==
@ -2752,6 +2715,13 @@ fast-safe-stringify@^2.1.1:
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
fast-url-parser@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"
integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==
dependencies:
punycode "^1.3.2"
fb-watchman@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85"
@ -4027,6 +3997,13 @@ koa-passport@4.1.4:
dependencies:
passport "^0.4.0"
koa-pino-logger@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/koa-pino-logger/-/koa-pino-logger-4.0.0.tgz#a45c9fd0a39e9cd84ac23da502055054ee51b80d"
integrity sha512-YI/LB9ajyLPpjvf6e+7Ewmn+OQkCJpu/Y9eI1n7fnipu5Y1NchuNlke0mqh3/2z+5oDYr7pijjOWruEDIfua2A==
dependencies:
pino-http "^6.5.0"
koa@2.13.4, koa@^2.13.4:
version "2.13.4"
resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e"
@ -4623,6 +4600,11 @@ object-inspect@^1.9.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
on-exit-leak-free@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209"
integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==
on-exit-leak-free@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4"
@ -4857,7 +4839,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0:
pino-abstract-transport@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
@ -4865,10 +4847,28 @@ pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0:
readable-stream "^4.0.0"
split2 "^4.0.0"
pino-pretty@*:
version "9.1.1"
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-9.1.1.tgz#e7d64c1db98266ca428ab56567b844ba780cd0e1"
integrity sha512-iJrnjgR4FWQIXZkUF48oNgoRI9BpyMhaEmihonHeCnZ6F50ZHAS4YGfGBT/ZVNsPmd+hzkIPGzjKdY08+/yAXw==
pino-abstract-transport@v0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0"
integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==
dependencies:
duplexify "^4.1.2"
split2 "^4.0.0"
pino-http@^6.5.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-6.6.0.tgz#d0a1deacada8c93327fdaa48f5bdc94bc43d3407"
integrity sha512-PlItaK2MLpoIMLEcClhfb1VQk/o6fKppINl5s6sPE/4rvufkdO3kCSs/92EwrBsB1yssRCQqDV+w1xpYuPVnjg==
dependencies:
fast-url-parser "^1.1.3"
get-caller-file "^2.0.5"
pino "^7.5.0"
pino-std-serializers "^5.0.0"
pino-pretty@10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-10.0.0.tgz#fd2f307ee897289f63d09b0b804ac2ecc9a18516"
integrity sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q==
dependencies:
colorette "^2.0.7"
dateformat "^4.6.3"
@ -4885,27 +4885,32 @@ pino-pretty@*:
sonic-boom "^3.0.0"
strip-json-comments "^3.1.1"
pino-std-serializers@*, pino-std-serializers@^6.0.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.1.0.tgz#307490fd426eefc95e06067e85d8558603e8e844"
integrity sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g==
pino-std-serializers@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2"
integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==
pino@*:
version "8.8.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-8.8.0.tgz#1f0d6695a224aa06afc7ad60f2ccc4772d3b9233"
integrity sha512-cF8iGYeu2ODg2gIwgAHcPrtR63ILJz3f7gkogaHC/TXVVXxZgInmNYiIpDYEwgEkxZti2Se6P2W2DxlBIZe6eQ==
pino-std-serializers@^5.0.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-5.6.0.tgz#31b141155d6520967c5ec72944d08fb45c490fd3"
integrity sha512-VdUXCw8gO+xhir7sFuoYSjTnzB+TMDGxhAC/ph3YS3sdHnXNdsK0wMtADNUltfeGkn2KDxEM21fnjF3RwXyC8A==
pino@^7.5.0:
version "7.11.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6"
integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.1.1"
on-exit-leak-free "^2.1.0"
pino-abstract-transport v1.0.0
pino-std-serializers "^6.0.0"
process-warning "^2.0.0"
fast-redact "^3.0.0"
on-exit-leak-free "^0.2.0"
pino-abstract-transport v0.5.0
pino-std-serializers "^4.0.0"
process-warning "^1.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.2.0"
safe-stable-stringify "^2.3.1"
sonic-boom "^3.1.0"
thread-stream "^2.0.0"
real-require "^0.1.0"
safe-stable-stringify "^2.1.0"
sonic-boom "^2.2.1"
thread-stream "^0.15.1"
pirates@^4.0.4:
version "4.0.5"
@ -5156,10 +5161,10 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
process-warning@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.1.0.tgz#1e60e3bfe8183033bbc1e702c2da74f099422d1a"
integrity sha512-9C20RLxrZU/rFnxWncDkuF6O999NdIf3E1ws4B0ZeY3sRVPzWBMsYDE2lxjxhiXxg464cQTgKUGm8/i6y2YGXg==
process-warning@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616"
integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==
process@^0.11.10:
version "0.11.10"
@ -5207,6 +5212,11 @@ punycode@1.3.2:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==
punycode@^1.3.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
@ -5330,10 +5340,10 @@ readline-sync@^1.4.9:
resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==
real-require@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
real-require@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381"
integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==
redis-commands@1.7.0:
version "1.7.0"
@ -5477,7 +5487,7 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-stable-stringify@^2.3.1:
safe-stable-stringify@^2.1.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz#ec7b037768098bf65310d1d64370de0dc02353aa"
integrity sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==
@ -5589,14 +5599,14 @@ slash@^3.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
sonic-boom@^2.1.0:
sonic-boom@^2.2.1:
version "2.8.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611"
integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==
dependencies:
atomic-sleep "^1.0.0"
sonic-boom@^3.0.0, sonic-boom@^3.1.0:
sonic-boom@^3.0.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.1.tgz#972ceab831b5840a08a002fa95a672008bda1c38"
integrity sha512-iITeTHxy3B9FGu8aVdiDXUVAcHMF9Ss0cCsAOo2HfCrmVGT3/DT5oYaeu0M/YKZDlKTvChEyPq0zI9Hf33EX6A==
@ -5701,6 +5711,11 @@ step@0.0.x:
resolved "https://registry.yarnpkg.com/step/-/step-0.0.6.tgz#143e7849a5d7d3f4a088fe29af94915216eeede2"
integrity sha512-qSSeQinUJk2w38vUFobjFoE307GqsozMC8VisOCkJLpklvKPT0ptPHwWOrENoag8rgLudvTkfP3bancwP93/Jw==
stream-shift@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
stream-to-array@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353"
@ -5897,12 +5912,12 @@ testcontainers@4.7.0:
stream-to-array "^2.3.0"
tar-fs "^2.1.0"
thread-stream@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33"
integrity sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==
thread-stream@^0.15.1:
version "0.15.2"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4"
integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==
dependencies:
real-require "^0.2.0"
real-require "^0.1.0"
through2@3.0.2:
version "3.0.2"

View File

@ -1,7 +1,7 @@
{
"name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"license": "MPL-2.0",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",
@ -38,8 +38,8 @@
],
"dependencies": {
"@adobe/spectrum-css-workflow-icons": "1.2.1",
"@budibase/shared-core": "2.4.44-alpha.5",
"@budibase/string-templates": "2.4.44-alpha.5",
"@budibase/shared-core": "2.4.44-alpha.9",
"@budibase/string-templates": "2.4.44-alpha.9",
"@spectrum-css/accordion": "3.0.24",
"@spectrum-css/actionbutton": "1.0.1",
"@spectrum-css/actiongroup": "1.0.1",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"license": "GPL-3.0",
"private": true,
"scripts": {
@ -58,11 +58,11 @@
}
},
"dependencies": {
"@budibase/bbui": "2.4.44-alpha.5",
"@budibase/client": "2.4.44-alpha.5",
"@budibase/frontend-core": "2.4.44-alpha.5",
"@budibase/shared-core": "2.4.44-alpha.5",
"@budibase/string-templates": "2.4.44-alpha.5",
"@budibase/bbui": "2.4.44-alpha.9",
"@budibase/client": "2.4.44-alpha.9",
"@budibase/frontend-core": "2.4.44-alpha.9",
"@budibase/shared-core": "2.4.44-alpha.9",
"@budibase/string-templates": "2.4.44-alpha.9",
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-brands-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",

View File

@ -1,10 +0,0 @@
{
"reporterEnabled": "mochawesome",
"mochawesomeReporterOptions": {
"reportDir": "cypress/reports",
"quiet": true,
"overwrite": false,
"html": false,
"json": true
}
}

View File

@ -1,43 +0,0 @@
const testConfig = require("./testConfig.json")
// normal development system
const SERVER_PORT = testConfig.env.PORT
const WORKER_PORT = testConfig.env.WORKER_PORT
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = "cypress"
}
process.env.ENABLE_ANALYTICS = "0"
process.env.JWT_SECRET = testConfig.env.JWT_SECRET
process.env.SELF_HOSTED = 1
process.env.WORKER_URL = `http://localhost:${WORKER_PORT}/`
process.env.APPS_URL = `http://localhost:${SERVER_PORT}/`
process.env.MINIO_URL = `http://localhost:4004`
process.env.MINIO_ACCESS_KEY = "budibase"
process.env.MINIO_SECRET_KEY = "budibase"
process.env.COUCH_DB_USER = "budibase"
process.env.COUCH_DB_PASSWORD = "budibase"
process.env.INTERNAL_API_KEY = "budibase"
process.env.ALLOW_DEV_AUTOMATIONS = 1
process.env.MOCK_REDIS = 1
// Stop info logs polluting test outputs
process.env.LOG_LEVEL = "error"
exports.run = (serverLoc = "../server/dist", workerLoc = "../worker/dist") => {
// require("dotenv").config({ path: resolve(dir, ".env") })
// don't make this a variable or top level require
// it will cause environment module to be loaded prematurely
// override the port with the worker port temporarily
process.env.PORT = WORKER_PORT
require(workerLoc)
// override the port with the server port
process.env.PORT = SERVER_PORT
require(serverLoc)
}
if (require.main === module) {
exports.run()
}

View File

@ -1,13 +0,0 @@
{
"baseUrl": "http://localhost:4100",
"projectId": "bmbemn",
"reporterOptions": {
"configFile": "reporterConfig.json"
},
"env": {
"PORT": "4100",
"WORKER_PORT": "4200",
"JWT_SECRET": "test",
"HOST_IP": ""
}
}

View File

@ -1,4 +0,0 @@
// @ts-ignore
import { run } from "../setup"
run("../server/src/index", "../worker/src/index")

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/cli",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "dist/index.js",
"bin": {
@ -29,9 +29,9 @@
"outputPath": "build"
},
"dependencies": {
"@budibase/backend-core": "2.4.44-alpha.5",
"@budibase/string-templates": "2.4.44-alpha.5",
"@budibase/types": "2.4.44-alpha.5",
"@budibase/backend-core": "2.4.44-alpha.9",
"@budibase/string-templates": "2.4.44-alpha.9",
"@budibase/types": "2.4.44-alpha.9",
"axios": "0.21.2",
"chalk": "4.1.0",
"cli-progress": "3.11.2",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/client",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"license": "MPL-2.0",
"module": "dist/budibase-client.js",
"main": "dist/budibase-client.js",
@ -19,11 +19,11 @@
"dev:builder": "rollup -cw"
},
"dependencies": {
"@budibase/bbui": "2.4.44-alpha.5",
"@budibase/frontend-core": "2.4.44-alpha.5",
"@budibase/shared-core": "2.4.44-alpha.5",
"@budibase/string-templates": "2.4.44-alpha.5",
"@budibase/types": "2.4.44-alpha.5",
"@budibase/bbui": "2.4.44-alpha.9",
"@budibase/frontend-core": "2.4.44-alpha.9",
"@budibase/shared-core": "2.4.44-alpha.9",
"@budibase/string-templates": "2.4.44-alpha.9",
"@budibase/types": "2.4.44-alpha.9",
"@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3",

View File

@ -1,13 +1,13 @@
{
"name": "@budibase/frontend-core",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase",
"license": "MPL-2.0",
"svelte": "src/index.js",
"dependencies": {
"@budibase/bbui": "2.4.44-alpha.5",
"@budibase/shared-core": "2.4.44-alpha.5",
"@budibase/bbui": "2.4.44-alpha.9",
"@budibase/shared-core": "2.4.44-alpha.9",
"lodash": "^4.17.21",
"svelte": "^3.46.2"
}

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/sdk",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Budibase Public API SDK",
"author": "Budibase",
"license": "MPL-2.0",

View File

@ -1,7 +1,7 @@
{
"name": "@budibase/server",
"email": "hi@budibase.com",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Budibase Web Server",
"main": "src/index.ts",
"repository": {
@ -26,6 +26,7 @@
"dev:stack:down": "node scripts/dev/manage.js down",
"dev:stack:nuke": "node scripts/dev/manage.js nuke",
"dev:builder": "yarn run dev:stack:up && nodemon",
"dev:built": "yarn run dev:stack:up && yarn run run:docker",
"specs": "ts-node specs/generate.ts && openapi-typescript specs/openapi.yaml --output src/definitions/openapi.ts",
"initialise": "node scripts/initialise.js",
"env:multi:enable": "node scripts/multiTenancy.js enable",
@ -44,12 +45,12 @@
"license": "GPL-3.0",
"dependencies": {
"@apidevtools/swagger-parser": "10.0.3",
"@budibase/backend-core": "2.4.44-alpha.5",
"@budibase/client": "2.4.44-alpha.5",
"@budibase/pro": "2.4.44-alpha.5",
"@budibase/shared-core": "2.4.44-alpha.5",
"@budibase/string-templates": "2.4.44-alpha.5",
"@budibase/types": "2.4.44-alpha.5",
"@budibase/backend-core": "2.4.44-alpha.9",
"@budibase/client": "2.4.44-alpha.9",
"@budibase/pro": "2.4.44-alpha.9",
"@budibase/shared-core": "2.4.44-alpha.9",
"@budibase/string-templates": "2.4.44-alpha.9",
"@budibase/types": "2.4.44-alpha.9",
"@bull-board/api": "3.7.0",
"@bull-board/koa": "3.9.4",
"@elastic/elasticsearch": "7.10.0",
@ -85,7 +86,6 @@
"koa-body": "4.2.0",
"koa-compress": "4.0.1",
"koa-connect": "2.1.0",
"koa-pino-logger": "3.0.0",
"koa-send": "5.0.0",
"koa-session": "5.12.0",
"koa-static": "5.0.0",
@ -99,7 +99,6 @@
"node-fetch": "2.6.7",
"open": "8.4.0",
"pg": "8.5.1",
"pino-pretty": "5.1.3",
"posthog-node": "1.3.0",
"pouchdb": "7.3.0",
"pouchdb-adapter-memory": "7.2.2",

View File

@ -45,6 +45,8 @@ async function init() {
BB_ADMIN_USER_PASSWORD: "",
PLUGINS_DIR: "",
TENANT_FEATURE_FLAGS: "*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR",
HTTP_MIGRATIONS: "0",
HTTP_LOGGING: "0",
}
let envFile = ""
Object.keys(envFileJson).forEach(key => {

View File

@ -1,35 +0,0 @@
/******************************************************
* This script just makes it easy to re-create *
* a cypress like environment for testing the backend *
******************************************************/
import path from "path"
const tmpdir = path.join(require("os").tmpdir(), ".budibase")
const SERVER_PORT = "4100"
const WORKER_PORT = "4200"
// @ts-ignore
process.env.NODE_ENV = "cypress"
process.env.ENABLE_ANALYTICS = "0"
process.env.JWT_SECRET = "budibase"
process.env.COUCH_URL = `leveldb://${tmpdir}/.data/`
process.env.SELF_HOSTED = "1"
process.env.WORKER_URL = `http://localhost:${WORKER_PORT}/`
process.env.MINIO_URL = `http://localhost:4004`
process.env.MINIO_ACCESS_KEY = "budibase"
process.env.MINIO_SECRET_KEY = "budibase"
process.env.COUCH_DB_USER = "budibase"
process.env.COUCH_DB_PASSWORD = "budibase"
process.env.INTERNAL_API_KEY = "budibase"
process.env.ALLOW_DEV_AUTOMATIONS = "1"
// don't make this a variable or top level require
// it will cause environment module to be loaded prematurely
// override the port with the worker port temporarily
process.env.PORT = WORKER_PORT
const worker = require("../../worker/src/index")
// override the port with the server port
process.env.PORT = SERVER_PORT
const server = require("../src/app")

View File

@ -0,0 +1,32 @@
import { Ctx } from "@budibase/types"
import { logging } from "@budibase/backend-core"
interface LogRequest {
message: string
data?: any
}
interface ErrorRequest {
message: string
}
export async function log(ctx: Ctx<LogRequest>) {
const body = ctx.request.body
console.trace(body.message, body.data)
console.debug(body.message, body.data)
console.info(body.message, body.data)
console.warn(body.message, body.data)
console.error(body.message, body.data)
ctx.status = 204
}
export async function alert(ctx: Ctx<ErrorRequest>) {
const body = ctx.request.body
logging.logAlert(body.message, new Error(body.message))
ctx.status = 204
}
export async function error(ctx: Ctx<ErrorRequest>) {
const body = ctx.request.body
throw new Error(body.message)
}

View File

@ -25,6 +25,7 @@ import devRoutes from "./dev"
import cloudRoutes from "./cloud"
import migrationRoutes from "./migrations"
import pluginRoutes from "./plugin"
import opsRoutes from "./ops"
import Router from "@koa/router"
import { api as pro } from "@budibase/pro"
@ -63,6 +64,7 @@ export const mainRoutes: Router[] = [
rowRoutes,
migrationRoutes,
pluginRoutes,
opsRoutes,
scheduleRoutes,
environmentVariableRoutes,
// these need to be handled last as they still use /api/:tableId

View File

@ -0,0 +1,30 @@
import Router from "@koa/router"
import * as controller from "../controllers/ops"
import { middleware } from "@budibase/backend-core"
import Joi from "joi"
export function logsValidator() {
return middleware.joiValidator.body(
Joi.object({
message: Joi.string().required(),
data: Joi.object(),
})
)
}
export function errorValidator() {
return middleware.joiValidator.body(
Joi.object({
message: Joi.string().required(),
})
)
}
const router: Router = new Router()
router
.post("/api/ops/log", logsValidator(), controller.log)
.post("/api/ops/error", errorValidator(), controller.error)
.post("/api/ops/alert", errorValidator(), controller.alert)
export default router

View File

@ -57,6 +57,7 @@ describe("/users", () => {
it("should be able to update the user", async () => {
const user = await config.createUser({ id: `us_update${utils.newid()}` })
user.roleId = BUILTIN_ROLE_IDS.BASIC
delete user._rev
const res = await request
.put(`/api/users/metadata`)
.set(config.defaultHeaders())
@ -65,6 +66,46 @@ describe("/users", () => {
.expect("Content-Type", /json/)
expect(res.body.ok).toEqual(true)
})
it("should be able to update the user multiple times", async () => {
const user = await config.createUser()
delete user._rev
const res1 = await request
.put(`/api/users/metadata`)
.set(config.defaultHeaders())
.send({ ...user, roleId: BUILTIN_ROLE_IDS.BASIC })
.expect(200)
.expect("Content-Type", /json/)
const res = await request
.put(`/api/users/metadata`)
.set(config.defaultHeaders())
.send({ ...user, _rev: res1.body.rev, roleId: BUILTIN_ROLE_IDS.POWER })
.expect(200)
.expect("Content-Type", /json/)
expect(res.body.ok).toEqual(true)
})
it("should require the _rev field for multiple updates", async () => {
const user = await config.createUser()
delete user._rev
await request
.put(`/api/users/metadata`)
.set(config.defaultHeaders())
.send({ ...user, roleId: BUILTIN_ROLE_IDS.BASIC })
.expect(200)
.expect("Content-Type", /json/)
await request
.put(`/api/users/metadata`)
.set(config.defaultHeaders())
.send({ ...user, roleId: BUILTIN_ROLE_IDS.POWER })
.expect(409)
.expect("Content-Type", /json/)
})
})
describe("destroy", () => {
@ -92,6 +133,7 @@ describe("/users", () => {
expect(res.body.tableId).toBeDefined()
})
})
describe("setFlag", () => {
it("should throw an error if a flag is not provided", async () => {
await config.createUser()
@ -101,8 +143,9 @@ describe("/users", () => {
.send({ value: "test" })
.expect(400)
.expect("Content-Type", /json/)
expect(res.body.message).toEqual("Must supply a 'flag' field in request body.")
expect(res.body.message).toEqual(
"Must supply a 'flag' field in request body."
)
})
it("should be able to set a flag on the user", async () => {
@ -146,8 +189,9 @@ describe("/users", () => {
.send({ value: "test" })
.expect(400)
.expect("Content-Type", /json/)
expect(res.body.message).toEqual("Must supply a 'flag' field in request body.")
expect(res.body.message).toEqual(
"Must supply a 'flag' field in request body."
)
})
it("should be able to set a flag on the user", async () => {
@ -165,33 +209,37 @@ describe("/users", () => {
describe("syncUser", () => {
it("should sync the user", async () => {
let user = await config.createUser()
await config.createApp('New App')
await config.createApp("New App")
let res = await request
.post(`/api/users/metadata/sync/${user._id}`)
.set(config.defaultHeaders())
.expect(200)
.expect("Content-Type", /json/)
expect(res.body.message).toEqual('User synced.')
expect(res.body.message).toEqual("User synced.")
})
it("should sync the user when a previous user is specified", async () => {
const app1 = await config.createApp('App 1')
const app2 = await config.createApp('App 2')
const app1 = await config.createApp("App 1")
const app2 = await config.createApp("App 2")
let user = await config.createUser({
builder: false,
admin: true,
roles: { [app1.appId]: 'ADMIN' }
})
roles: { [app1.appId]: "ADMIN" },
})
let res = await request
.post(`/api/users/metadata/sync/${user._id}`)
.set(config.defaultHeaders())
.send({ previousUser: { ...user, roles: { ...user.roles, [app2.appId]: 'BASIC' } } })
.send({
previousUser: {
...user,
roles: { ...user.roles, [app2.appId]: "BASIC" },
},
})
.expect(200)
.expect("Content-Type", /json/)
expect(res.body.message).toEqual('User synced.')
expect(res.body.message).toEqual("User synced.")
})
})
})

View File

@ -2,21 +2,9 @@ if (process.env.DD_APM_ENABLED) {
require("./ddApm")
}
if (process.env.ELASTIC_APM_ENABLED) {
require("./elasticApm")
}
// need to load environment first
import env from "./environment"
// enable APM if configured
if (process.env.ELASTIC_APM_ENABLED) {
const apm = require("elastic-apm-node").start({
serviceName: process.env.SERVICE,
environment: process.env.BUDIBASE_ENVIRONMENT,
})
}
import { ExtendableContext } from "koa"
import * as db from "./db"
db.init()
@ -53,7 +41,8 @@ app.use(
})
)
app.use(middleware.logging)
app.use(middleware.correlation)
app.use(middleware.pino)
app.use(userAgent)
if (env.isProd()) {

View File

@ -1,10 +0,0 @@
import apm from "elastic-apm-node"
// enable APM if configured
if (process.env.ELASTIC_APM_ENABLED) {
console.log("Starting elastic-apm-node")
apm.start({
serviceName: process.env.SERVICE,
environment: process.env.BUDIBASE_ENVIRONMENT,
})
}

View File

@ -62,7 +62,6 @@ const environment = {
// minor
SALT_ROUNDS: process.env.SALT_ROUNDS,
LOGGER: process.env.LOGGER,
LOG_LEVEL: process.env.LOG_LEVEL,
ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
AUTOMATION_MAX_ITERATIONS:
parseIntSafe(process.env.AUTOMATION_MAX_ITERATIONS) || 200,

View File

@ -9,6 +9,6 @@ export const run = async () => {
// sync app count
const tenantId = tenancy.getTenantId()
console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`)
console.log(`Syncing app count: ${appCount}`)
await quotas.setUsage(appCount, StaticQuotaName.APPS, QuotaUsageType.STATIC)
}

View File

@ -1,4 +1,4 @@
import { tenancy, db as dbCore } from "@budibase/backend-core"
import { db as dbCore } from "@budibase/backend-core"
import { getUniqueRows } from "../../../utilities/usageQuota/rows"
import { quotas } from "@budibase/pro"
import { StaticQuotaName, QuotaUsageType, App } from "@budibase/types"
@ -18,8 +18,7 @@ export const run = async () => {
})
// sync row count
const tenantId = tenancy.getTenantId()
console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`)
console.log(`Syncing row count: ${rowCount}`)
await quotas.setUsagePerApp(
counts,
StaticQuotaName.ROWS,

View File

@ -16,13 +16,10 @@ import * as bullboard from "./automations/bullboard"
import * as pro from "@budibase/pro"
import * as api from "./api"
import sdk from "./sdk"
const pino = require("koa-pino-logger")
let STARTUP_RAN = false
async function initRoutes(app: any) {
app.use(pino(logging.pinoSettings()))
if (!env.isTest()) {
const plugin = await bullboard.init()
app.use(plugin)
@ -48,8 +45,10 @@ async function initPro() {
}
function shutdown(server?: any) {
server.close()
server.destroy()
if (server) {
server.close()
server.destroy()
}
}
export async function startup(app?: any, server?: any) {
@ -73,39 +72,7 @@ export async function startup(app?: any, server?: any) {
await migrations.migrate()
} catch (e) {
logging.logAlert("Error performing migrations. Exiting.", e)
shutdown()
}
}
// check and create admin user if required
if (
env.SELF_HOSTED &&
!env.MULTI_TENANCY &&
env.BB_ADMIN_USER_EMAIL &&
env.BB_ADMIN_USER_PASSWORD
) {
const checklist = await getChecklist()
if (!checklist?.adminUser?.checked) {
try {
const tenantId = tenancy.getTenantId()
const user = await createAdminUser(
env.BB_ADMIN_USER_EMAIL,
env.BB_ADMIN_USER_PASSWORD,
tenantId
)
// Need to set up an API key for automated integration tests
if (env.isTest()) {
await generateApiKey(user._id)
}
console.log(
"Admin account automatically created for",
env.BB_ADMIN_USER_EMAIL
)
} catch (e) {
logging.logAlert("Error creating initial admin user. Exiting.", e)
shutdown()
}
shutdown(server)
}
}
@ -134,4 +101,38 @@ export async function startup(app?: any, server?: any) {
// bring routes online as final step once everything ready
await initRoutes(app)
}
// check and create admin user if required
// this must be run after the api has been initialised due to
// the app user sync
if (
env.SELF_HOSTED &&
!env.MULTI_TENANCY &&
env.BB_ADMIN_USER_EMAIL &&
env.BB_ADMIN_USER_PASSWORD
) {
const checklist = await getChecklist()
if (!checklist?.adminUser?.checked) {
try {
const tenantId = tenancy.getTenantId()
const user = await createAdminUser(
env.BB_ADMIN_USER_EMAIL,
env.BB_ADMIN_USER_PASSWORD,
tenantId
)
// Need to set up an API key for automated integration tests
if (env.isTest()) {
await generateApiKey(user._id)
}
console.log(
"Admin account automatically created for",
env.BB_ADMIN_USER_EMAIL
)
} catch (e) {
logging.logAlert("Error creating initial admin user. Exiting.", e)
shutdown(server)
}
}
}
}

View File

@ -6,7 +6,6 @@ process.env.MULTI_TENANCY = "1"
// @ts-ignore
process.env.BUDIBASE_DIR = tmpdir("budibase-unittests")
process.env.LOG_LEVEL = process.env.LOG_LEVEL || "error"
process.env.ENABLE_4XX_HTTP_LOGGING = "0"
process.env.MOCK_REDIS = "1"
process.env.PLATFORM_URL = "http://localhost:10000"
process.env.REDIS_PASSWORD = "budibase"

View File

@ -1,4 +1,3 @@
import "./logging"
import env from "../environment"
import { env as coreEnv, timers } from "@budibase/backend-core"
import { testContainerUtils } from "@budibase/backend-core/tests"

View File

@ -1,34 +0,0 @@
export enum LogLevel {
TRACE = "trace",
DEBUG = "debug",
INFO = "info",
WARN = "warn",
ERROR = "error",
}
const LOG_INDEX: { [key in LogLevel]: number } = {
[LogLevel.TRACE]: 1,
[LogLevel.DEBUG]: 2,
[LogLevel.INFO]: 3,
[LogLevel.WARN]: 4,
[LogLevel.ERROR]: 5,
}
const setIndex = LOG_INDEX[process.env.LOG_LEVEL as LogLevel]
if (setIndex > LOG_INDEX.trace) {
global.console.trace = jest.fn()
}
if (setIndex > LOG_INDEX.debug) {
global.console.debug = jest.fn()
}
if (setIndex > LOG_INDEX.info) {
global.console.info = jest.fn()
global.console.log = jest.fn()
}
if (setIndex > LOG_INDEX.warn) {
global.console.warn = jest.fn()
}

View File

@ -1290,14 +1290,14 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@2.4.44-alpha.5":
version "2.4.44-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.44-alpha.5.tgz#072082d5322a27b9cfaee75718ddcf464afaec13"
integrity sha512-TRiepsq3MlQ0ZqZoRJDmYUUTb31gURPvHs6CmfqR1wP0sh+yf+5PgmLQDLLXTHOZ7b461yp5KDVC9OjNsna3WQ==
"@budibase/backend-core@2.4.44-alpha.9":
version "2.4.44-alpha.9"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.44-alpha.9.tgz#ea2f1ec39fe0a97172b00e551f9e3b51f860e53b"
integrity sha512-uuZEqeyXnVwyNDPSwI8gF8zCv26PWvhbLoEYXMQqNl9J9q5g4i/lNacfKs1x9JDPABHE93mtLL5eoTogzrqTIg==
dependencies:
"@budibase/nano" "10.1.2"
"@budibase/pouchdb-replication-stream" "1.2.10"
"@budibase/types" "2.4.44-alpha.5"
"@budibase/types" "2.4.44-alpha.9"
"@shopify/jest-koa-mocks" "5.0.1"
"@techpass/passport-openidconnect" "0.3.2"
aws-cloudfront-sign "2.2.0"
@ -1312,6 +1312,7 @@
joi "17.6.0"
jsonwebtoken "9.0.0"
koa-passport "4.1.4"
koa-pino-logger "4.0.0"
lodash "4.17.21"
lodash.isarguments "3.1.0"
node-fetch "2.6.7"
@ -1429,15 +1430,15 @@
pouchdb-promise "^6.0.4"
through2 "^2.0.0"
"@budibase/pro@2.4.44-alpha.5":
version "2.4.44-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.44-alpha.5.tgz#c748dfc16f5b30226c4006ae42a07636e5499102"
integrity sha512-HTKFiglaRb3aii4XakLezyLteo4SAg2ZumH6o/FSaRPrcN4KlPjxVCSxhXVSxu3m6GMdbcGLlah7+lK6iHnyEA==
"@budibase/pro@2.4.44-alpha.9":
version "2.4.44-alpha.9"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.44-alpha.9.tgz#f6a5bcfb607ebb2138762e53a04ad55cf6de6014"
integrity sha512-cPUXlt9XQ0DlwoR47wLiLGEQlib6vKW15cLkh0pkz57vHbr5T22Ix4G7vgKGPVr5kpaJVNVdYLxBZ3qy8hUnJQ==
dependencies:
"@budibase/backend-core" "2.4.44-alpha.5"
"@budibase/backend-core" "2.4.44-alpha.9"
"@budibase/shared-core" "2.4.44-alpha.1"
"@budibase/string-templates" "2.4.44-alpha.1"
"@budibase/types" "2.4.44-alpha.5"
"@budibase/types" "2.4.44-alpha.9"
"@koa/router" "8.0.8"
bull "4.10.1"
joi "17.6.0"
@ -1490,10 +1491,10 @@
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.44-alpha.1.tgz#1679657aa180d9c59afa1dffa611bff0638bd933"
integrity sha512-Sq+8HfM75EBMoOvKYFwELdlxmVN6wNZMofDjT/2G+9aF+Zfe5Tzw69C+unmdBgcGGjGCHEYWSz4mF0v8FPAGbg==
"@budibase/types@2.4.44-alpha.5":
version "2.4.44-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.44-alpha.5.tgz#42c56241ab29ef81a048b93bc84644b69e41e63b"
integrity sha512-ACco4vREtv1un3aMH2sTKI8kD+/Hly2ee9AZw9YxFlsl78sOkvBPD25ki7oc8GH2pjLQ1Sjw7yG3SgW8MIsdbg==
"@budibase/types@2.4.44-alpha.9":
version "2.4.44-alpha.9"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.44-alpha.9.tgz#a64fad8252f196bcb2a5fbd53f89ff5a90745813"
integrity sha512-auXyD1A1MZ42KYMaQpnHBgXbR3O3t6oycYESwhbkIaTHw3f9ir3m8Sus5R1eMI7YqI8nWjB6y9tW6lZoIAd/Pg==
dependencies:
scim-patch "^0.7.0"
@ -1677,11 +1678,6 @@
protobufjs "^6.11.3"
yargs "^16.2.0"
"@hapi/bourne@^2.0.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.1.0.tgz#66aff77094dc3080bd5df44ec63881f2676eb020"
integrity sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==
"@hapi/hoek@^9.0.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
@ -4168,16 +4164,6 @@ argparse@^2.0.1:
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
args@^5.0.1:
version "5.0.3"
resolved "https://registry.yarnpkg.com/args/-/args-5.0.3.tgz#943256db85021a85684be2f0882f25d796278702"
integrity sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==
dependencies:
camelcase "5.0.0"
chalk "2.4.2"
leven "2.1.0"
mri "1.1.4"
argsarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb"
@ -4992,11 +4978,6 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
camelcase@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==
camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
@ -5022,7 +5003,7 @@ caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0:
chalk@^2.0.0, chalk@^2.1.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@ -5617,11 +5598,6 @@ date-utils@*:
resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64"
integrity sha512-wJMBjqlwXR0Iv0wUo/lFbhSQ7MmG1hl36iuxuE91kW+5b5sWbase73manEqNH9sOLFAMG83B4ffNKq9/Iq0FVA==
dateformat@^4.5.1:
version "4.6.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5"
integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==
dayjs@^1.10.4, dayjs@^1.10.5:
version "1.11.3"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.3.tgz#4754eb694a624057b9ad2224b67b15d552589258"
@ -6041,7 +6017,7 @@ duplexer3@^0.1.4:
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==
duplexify@^4.0.0:
duplexify@^4.0.0, duplexify@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==
@ -9281,7 +9257,7 @@ jimp@0.16.1:
"@jimp/types" "^0.16.1"
regenerator-runtime "^0.13.3"
jmespath@0.15.0, jmespath@^0.15.0:
jmespath@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
integrity sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==
@ -9307,7 +9283,7 @@ join-component@^1.1.0:
resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5"
integrity sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==
joycon@^3.0.0, joycon@^3.0.1:
joycon@^3.0.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
@ -9680,12 +9656,12 @@ koa-passport@4.1.4:
dependencies:
passport "^0.4.0"
koa-pino-logger@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/koa-pino-logger/-/koa-pino-logger-3.0.0.tgz#27600b4f3639e8767dfc6b66493109c5457f53ba"
integrity sha512-teJsT88JLRBYH7pJACGAwAHfl2y/x5u5aSPD03Z/HW6QDMAWyRxk4dsY0/UbtM8wgaXIaxZgIFUxxvgiQFr6WQ==
koa-pino-logger@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/koa-pino-logger/-/koa-pino-logger-4.0.0.tgz#a45c9fd0a39e9cd84ac23da502055054ee51b80d"
integrity sha512-YI/LB9ajyLPpjvf6e+7Ewmn+OQkCJpu/Y9eI1n7fnipu5Y1NchuNlke0mqh3/2z+5oDYr7pijjOWruEDIfua2A==
dependencies:
pino-http "^5.0.1"
pino-http "^6.5.0"
koa-router@^10.0.0:
version "10.1.1"
@ -9902,11 +9878,6 @@ levelup@4.4.0, levelup@^4.3.2:
level-supports "~1.0.0"
xtend "~4.0.0"
leven@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
integrity sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@ -10592,11 +10563,6 @@ monitor-event-loop-delay@^1.0.0:
resolved "https://registry.yarnpkg.com/monitor-event-loop-delay/-/monitor-event-loop-delay-1.0.0.tgz#b5ab78165a3bb93f2b275c50d01430c7f155d1f7"
integrity sha512-YRIr1exCIfBDLZle8WHOfSo7Xg3M+phcZfq9Fx1L6Abo+atGp7cge5pM7PjyBn4s1oZI/BRD4EMrzQBbPpVb5Q==
mri@1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a"
integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@ -11047,6 +11013,11 @@ omggif@^1.0.10, omggif@^1.0.9:
resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19"
integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==
on-exit-leak-free@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209"
integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==
on-finished@^2.3.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
@ -11618,32 +11589,23 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==
pino-http@^5.0.1:
version "5.8.0"
resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-5.8.0.tgz#6e688fd5f965c5b6991f340eb660ea2927be9aa7"
integrity sha512-YwXiyRb9y0WCD1P9PcxuJuh3Dc5qmXde/paJE86UGYRdiFOi828hR9iUGmk5gaw6NBT9gLtKANOHFimvh19U5w==
pino-abstract-transport@v0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0"
integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==
dependencies:
duplexify "^4.1.2"
split2 "^4.0.0"
pino-http@^6.5.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-6.6.0.tgz#d0a1deacada8c93327fdaa48f5bdc94bc43d3407"
integrity sha512-PlItaK2MLpoIMLEcClhfb1VQk/o6fKppINl5s6sPE/4rvufkdO3kCSs/92EwrBsB1yssRCQqDV+w1xpYuPVnjg==
dependencies:
fast-url-parser "^1.1.3"
pino "^6.13.0"
pino-std-serializers "^4.0.0"
pino-pretty@5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-5.1.3.tgz#c4085093d1dffda359ab52731f87d96f7f832dc9"
integrity sha512-Zj+0TVdYKkAAIx9EUCL5e4TttwgsaFvJh2ceIMQeFCY8ak9tseEZQGSgpvyjEj1/iIVGIh5tdhkGEQWSMILKHA==
dependencies:
"@hapi/bourne" "^2.0.0"
args "^5.0.1"
chalk "^4.0.0"
dateformat "^4.5.1"
fast-safe-stringify "^2.0.7"
jmespath "^0.15.0"
joycon "^3.0.0"
pump "^3.0.0"
readable-stream "^3.6.0"
rfdc "^1.3.0"
split2 "^3.1.1"
strip-json-comments "^3.1.1"
get-caller-file "^2.0.5"
pino "^7.5.0"
pino-std-serializers "^5.0.0"
pino-std-serializers@^3.1.0:
version "3.2.0"
@ -11655,7 +11617,12 @@ pino-std-serializers@^4.0.0:
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2"
integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==
pino@^6.11.2, pino@^6.13.0:
pino-std-serializers@^5.0.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-5.6.0.tgz#31b141155d6520967c5ec72944d08fb45c490fd3"
integrity sha512-VdUXCw8gO+xhir7sFuoYSjTnzB+TMDGxhAC/ph3YS3sdHnXNdsK0wMtADNUltfeGkn2KDxEM21fnjF3RwXyC8A==
pino@^6.11.2:
version "6.14.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78"
integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==
@ -11668,6 +11635,23 @@ pino@^6.11.2, pino@^6.13.0:
quick-format-unescaped "^4.0.3"
sonic-boom "^1.0.2"
pino@^7.5.0:
version "7.11.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6"
integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.0.0"
on-exit-leak-free "^0.2.0"
pino-abstract-transport v0.5.0
pino-std-serializers "^4.0.0"
process-warning "^1.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.1.0"
safe-stable-stringify "^2.1.0"
sonic-boom "^2.2.1"
thread-stream "^0.15.1"
pirates@^4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
@ -12275,7 +12259,7 @@ readable-stream@1.1.14, readable-stream@^1.0.27-1:
isarray "0.0.1"
string_decoder "~0.10.x"
"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
"readable-stream@2 || 3", readable-stream@^3.0.1, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@ -12324,6 +12308,11 @@ readline-sync@^1.4.9:
resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==
real-require@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381"
integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==
recast@^0.10.1:
version "0.10.43"
resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f"
@ -12687,7 +12676,7 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rfdc@^1.2.0, rfdc@^1.3.0:
rfdc@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
@ -12754,6 +12743,11 @@ safe-regex@^1.1.0:
dependencies:
ret "~0.1.10"
safe-stable-stringify@^2.1.0:
version "2.4.3"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
safe-stable-stringify@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73"
@ -13153,6 +13147,13 @@ sonic-boom@^1.0.2:
atomic-sleep "^1.0.0"
flatstr "^1.0.12"
sonic-boom@^2.2.1:
version "2.8.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611"
integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==
dependencies:
atomic-sleep "^1.0.0"
sort-keys-length@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188"
@ -13288,12 +13289,10 @@ split2@^2.1.0:
dependencies:
through2 "^2.0.2"
split2@^3.1.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f"
integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==
dependencies:
readable-stream "^3.0.0"
split2@^4.0.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
split2@^4.1.0:
version "4.1.0"
@ -13925,6 +13924,13 @@ thenify-all@^1.0.0:
dependencies:
any-promise "^1.0.0"
thread-stream@^0.15.1:
version "0.15.2"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4"
integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==
dependencies:
real-require "^0.1.0"
through2@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4"

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/shared-core",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Shared data utils",
"main": "dist/cjs/src/index.js",
"types": "dist/mjs/src/index.d.ts",
@ -20,7 +20,7 @@
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
},
"dependencies": {
"@budibase/types": "2.4.44-alpha.5"
"@budibase/types": "2.4.44-alpha.9"
},
"devDependencies": {
"concurrently": "^7.6.0",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/string-templates",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"module": "dist/bundle.mjs",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/types",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Budibase types",
"main": "dist/cjs/index.js",
"types": "dist/mjs/index.d.ts",

View File

@ -0,0 +1,13 @@
import { Hosting } from "../../sdk"
export interface CreateAccountRequest {
email: string
tenantId: string
hosting: Hosting
size: string
profession: string
// optional fields
tenantName?: string
name?: string
password: string
}

View File

@ -1,3 +1,4 @@
export * from "./accounts"
export * from "./user"
export * from "./license"
export * from "./status"

View File

@ -3,6 +3,7 @@ export * from "./auth"
export * from "./user"
export * from "./errors"
export * from "./schedule"
export * from "./system"
export * from "./app"
export * from "./global"
export * from "./pagination"

View File

@ -0,0 +1,8 @@
export interface GetEnvironmentResponse {
multiTenancy: boolean
cloud: boolean
accountPortalUrl: string
baseUrl: string
disableAccountPortal: boolean
isDev: boolean
}

View File

@ -0,0 +1 @@
export * from "./environment"

View File

@ -1,6 +1,7 @@
import Nano from "@budibase/nano"
import { AllDocsResponse, AnyDocument, Document } from "../"
import { Writable } from "stream"
import PouchDB from "pouchdb"
export enum SearchIndex {
ROWS = "rows",

View File

@ -1,7 +1,7 @@
{
"name": "@budibase/worker",
"email": "hi@budibase.com",
"version": "2.4.44-alpha.5",
"version": "2.4.44-alpha.9",
"description": "Budibase background service",
"main": "src/index.ts",
"repository": {
@ -22,6 +22,7 @@
"build:docker": "docker build . -t worker-service --label version=$BUDIBASE_RELEASE_VERSION",
"dev:stack:init": "node ./scripts/dev/manage.js init",
"dev:builder": "npm run dev:stack:init && nodemon",
"dev:built": "yarn run dev:stack:init && yarn run run:docker",
"test": "bash scripts/test.sh",
"test:watch": "jest --watch",
"env:multi:enable": "node scripts/multiTenancy.js enable",
@ -36,10 +37,10 @@
"author": "Budibase",
"license": "GPL-3.0",
"dependencies": {
"@budibase/backend-core": "2.4.44-alpha.5",
"@budibase/pro": "2.4.44-alpha.5",
"@budibase/string-templates": "2.4.44-alpha.5",
"@budibase/types": "2.4.44-alpha.5",
"@budibase/backend-core": "2.4.44-alpha.9",
"@budibase/pro": "2.4.44-alpha.9",
"@budibase/string-templates": "2.4.44-alpha.9",
"@budibase/types": "2.4.44-alpha.9",
"@koa/router": "8.0.8",
"@sentry/node": "6.17.7",
"@techpass/passport-openidconnect": "0.3.2",
@ -56,7 +57,6 @@
"koa-body": "4.2.0",
"koa-compress": "4.0.1",
"koa-passport": "4.1.4",
"koa-pino-logger": "3.0.0",
"koa-send": "5.0.1",
"koa-session": "5.13.1",
"koa-static": "5.0.0",
@ -66,7 +66,6 @@
"passport-google-oauth": "2.0.0",
"passport-jwt": "4.0.0",
"passport-local": "1.0.0",
"pino-pretty": "5.1.3",
"pouchdb": "7.3.0",
"pouchdb-all-dbs": "1.1.1",
"server-destroy": "1.0.1"

View File

@ -30,6 +30,7 @@ async function init() {
DEPLOYMENT_ENVIRONMENT: "development",
TENANT_FEATURE_FLAGS: "*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR",
ENABLE_EMAIL_TEST_MODE: 1,
HTTP_LOGGING: 0,
}
let envFile = ""
Object.keys(envFileJson).forEach(key => {

View File

@ -1,10 +0,0 @@
import apm from "elastic-apm-node"
// enable APM if configured
if (process.env.ELASTIC_APM_ENABLED) {
console.log("Starting elastic-apm-node")
apm.start({
serviceName: process.env.SERVICE,
environment: process.env.BUDIBASE_ENVIRONMENT,
})
}

View File

@ -47,7 +47,6 @@ const environment = {
// flags
NODE_ENV: process.env.NODE_ENV,
SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED || ""),
LOG_LEVEL: process.env.LOG_LEVEL,
MULTI_TENANCY: process.env.MULTI_TENANCY,
DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
SMTP_FALLBACK_ENABLED: process.env.SMTP_FALLBACK_ENABLED,

View File

@ -2,10 +2,6 @@ if (process.env.DD_APM_ENABLED) {
require("./ddApm")
}
if (process.env.ELASTIC_APM_ENABLED) {
require("./elasticApm")
}
// need to load environment first
import env from "./environment"
import { Scope } from "@sentry/node"
@ -31,7 +27,6 @@ import api from "./api"
import * as redis from "./utilities/redis"
const Sentry = require("@sentry/node")
const koaSession = require("koa-session")
const logger = require("koa-pino-logger")
const { userAgent } = require("koa-useragent")
import destroyable from "server-destroy"
@ -60,8 +55,8 @@ app.use(handleScimBody)
app.use(koaBody({ multipart: true }))
app.use(koaSession(app))
app.use(middleware.logging)
app.use(logger(logging.pinoSettings()))
app.use(middleware.correlation)
app.use(middleware.pino)
app.use(userAgent)
// authentication

View File

@ -2,7 +2,6 @@ process.env.SELF_HOSTED = "0"
process.env.NODE_ENV = "jest"
process.env.JWT_SECRET = "test-jwtsecret"
process.env.LOG_LEVEL = process.env.LOG_LEVEL || "error"
process.env.ENABLE_4XX_HTTP_LOGGING = "0"
process.env.MULTI_TENANCY = "1"
process.env.MINIO_URL = "http://localhost"
process.env.MINIO_ACCESS_KEY = "test"

View File

@ -1,5 +1,3 @@
import "./logging"
import { mocks, testContainerUtils } from "@budibase/backend-core/tests"
import env from "../environment"
import { env as coreEnv, timers } from "@budibase/backend-core"

View File

@ -1,34 +0,0 @@
export enum LogLevel {
TRACE = "trace",
DEBUG = "debug",
INFO = "info",
WARN = "warn",
ERROR = "error",
}
const LOG_INDEX: { [key in LogLevel]: number } = {
[LogLevel.TRACE]: 1,
[LogLevel.DEBUG]: 2,
[LogLevel.INFO]: 3,
[LogLevel.WARN]: 4,
[LogLevel.ERROR]: 5,
}
const setIndex = LOG_INDEX[process.env.LOG_LEVEL as LogLevel]
if (setIndex > LOG_INDEX.trace) {
global.console.trace = jest.fn()
}
if (setIndex > LOG_INDEX.debug) {
global.console.debug = jest.fn()
}
if (setIndex > LOG_INDEX.info) {
global.console.info = jest.fn()
global.console.log = jest.fn()
}
if (setIndex > LOG_INDEX.warn) {
global.console.warn = jest.fn()
}

View File

@ -475,14 +475,14 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@2.4.44-alpha.5":
version "2.4.44-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.44-alpha.5.tgz#072082d5322a27b9cfaee75718ddcf464afaec13"
integrity sha512-TRiepsq3MlQ0ZqZoRJDmYUUTb31gURPvHs6CmfqR1wP0sh+yf+5PgmLQDLLXTHOZ7b461yp5KDVC9OjNsna3WQ==
"@budibase/backend-core@2.4.44-alpha.9":
version "2.4.44-alpha.9"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.44-alpha.9.tgz#ea2f1ec39fe0a97172b00e551f9e3b51f860e53b"
integrity sha512-uuZEqeyXnVwyNDPSwI8gF8zCv26PWvhbLoEYXMQqNl9J9q5g4i/lNacfKs1x9JDPABHE93mtLL5eoTogzrqTIg==
dependencies:
"@budibase/nano" "10.1.2"
"@budibase/pouchdb-replication-stream" "1.2.10"
"@budibase/types" "2.4.44-alpha.5"
"@budibase/types" "2.4.44-alpha.9"
"@shopify/jest-koa-mocks" "5.0.1"
"@techpass/passport-openidconnect" "0.3.2"
aws-cloudfront-sign "2.2.0"
@ -497,6 +497,7 @@
joi "17.6.0"
jsonwebtoken "9.0.0"
koa-passport "4.1.4"
koa-pino-logger "4.0.0"
lodash "4.17.21"
lodash.isarguments "3.1.0"
node-fetch "2.6.7"
@ -564,15 +565,15 @@
pouchdb-promise "^6.0.4"
through2 "^2.0.0"
"@budibase/pro@2.4.44-alpha.5":
version "2.4.44-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.44-alpha.5.tgz#c748dfc16f5b30226c4006ae42a07636e5499102"
integrity sha512-HTKFiglaRb3aii4XakLezyLteo4SAg2ZumH6o/FSaRPrcN4KlPjxVCSxhXVSxu3m6GMdbcGLlah7+lK6iHnyEA==
"@budibase/pro@2.4.44-alpha.9":
version "2.4.44-alpha.9"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.44-alpha.9.tgz#f6a5bcfb607ebb2138762e53a04ad55cf6de6014"
integrity sha512-cPUXlt9XQ0DlwoR47wLiLGEQlib6vKW15cLkh0pkz57vHbr5T22Ix4G7vgKGPVr5kpaJVNVdYLxBZ3qy8hUnJQ==
dependencies:
"@budibase/backend-core" "2.4.44-alpha.5"
"@budibase/backend-core" "2.4.44-alpha.9"
"@budibase/shared-core" "2.4.44-alpha.1"
"@budibase/string-templates" "2.4.44-alpha.1"
"@budibase/types" "2.4.44-alpha.5"
"@budibase/types" "2.4.44-alpha.9"
"@koa/router" "8.0.8"
bull "4.10.1"
joi "17.6.0"
@ -607,10 +608,10 @@
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.44-alpha.1.tgz#1679657aa180d9c59afa1dffa611bff0638bd933"
integrity sha512-Sq+8HfM75EBMoOvKYFwELdlxmVN6wNZMofDjT/2G+9aF+Zfe5Tzw69C+unmdBgcGGjGCHEYWSz4mF0v8FPAGbg==
"@budibase/types@2.4.44-alpha.5":
version "2.4.44-alpha.5"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.44-alpha.5.tgz#42c56241ab29ef81a048b93bc84644b69e41e63b"
integrity sha512-ACco4vREtv1un3aMH2sTKI8kD+/Hly2ee9AZw9YxFlsl78sOkvBPD25ki7oc8GH2pjLQ1Sjw7yG3SgW8MIsdbg==
"@budibase/types@2.4.44-alpha.9":
version "2.4.44-alpha.9"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.44-alpha.9.tgz#a64fad8252f196bcb2a5fbd53f89ff5a90745813"
integrity sha512-auXyD1A1MZ42KYMaQpnHBgXbR3O3t6oycYESwhbkIaTHw3f9ir3m8Sus5R1eMI7YqI8nWjB6y9tW6lZoIAd/Pg==
dependencies:
scim-patch "^0.7.0"
@ -682,11 +683,6 @@
dependencies:
"@elastic/ecs-helpers" "^1.1.0"
"@hapi/bourne@^2.0.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.1.0.tgz#66aff77094dc3080bd5df44ec63881f2676eb020"
integrity sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==
"@hapi/hoek@^9.0.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
@ -2133,16 +2129,6 @@ argparse@^1.0.10, argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
args@^5.0.1:
version "5.0.3"
resolved "https://registry.yarnpkg.com/args/-/args-5.0.3.tgz#943256db85021a85684be2f0882f25d796278702"
integrity sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==
dependencies:
camelcase "5.0.0"
chalk "2.4.2"
leven "2.1.0"
mri "1.1.4"
argsarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb"
@ -2676,11 +2662,6 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
camelcase@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==
camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
@ -2706,7 +2687,7 @@ caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0:
chalk@^2.0.0, chalk@^2.1.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@ -3142,11 +3123,6 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
dateformat@^4.5.1:
version "4.6.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5"
integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==
dayjs@^1.10.4:
version "1.11.7"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2"
@ -3468,6 +3444,16 @@ duplexer3@^0.1.4:
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==
duplexify@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==
dependencies:
end-of-stream "^1.4.1"
inherits "^2.0.3"
readable-stream "^3.1.1"
stream-shift "^1.0.0"
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@ -5744,7 +5730,7 @@ jest@28.1.1:
import-local "^3.0.2"
jest-cli "^28.1.1"
jmespath@0.15.0, jmespath@^0.15.0:
jmespath@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
integrity sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==
@ -5765,11 +5751,6 @@ join-component@^1.1.0:
resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5"
integrity sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==
joycon@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@ -5998,12 +5979,12 @@ koa-passport@4.1.4:
dependencies:
passport "^0.4.0"
koa-pino-logger@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/koa-pino-logger/-/koa-pino-logger-3.0.0.tgz#27600b4f3639e8767dfc6b66493109c5457f53ba"
integrity sha512-teJsT88JLRBYH7pJACGAwAHfl2y/x5u5aSPD03Z/HW6QDMAWyRxk4dsY0/UbtM8wgaXIaxZgIFUxxvgiQFr6WQ==
koa-pino-logger@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/koa-pino-logger/-/koa-pino-logger-4.0.0.tgz#a45c9fd0a39e9cd84ac23da502055054ee51b80d"
integrity sha512-YI/LB9ajyLPpjvf6e+7Ewmn+OQkCJpu/Y9eI1n7fnipu5Y1NchuNlke0mqh3/2z+5oDYr7pijjOWruEDIfua2A==
dependencies:
pino-http "^5.0.1"
pino-http "^6.5.0"
koa-send@5.0.1, koa-send@^5.0.0:
version "5.0.1"
@ -6169,11 +6150,6 @@ levelup@4.4.0, levelup@^4.3.2:
level-supports "~1.0.0"
xtend "~4.0.0"
leven@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
integrity sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@ -6609,11 +6585,6 @@ monitor-event-loop-delay@^1.0.0:
resolved "https://registry.yarnpkg.com/monitor-event-loop-delay/-/monitor-event-loop-delay-1.0.0.tgz#b5ab78165a3bb93f2b275c50d01430c7f155d1f7"
integrity sha512-YRIr1exCIfBDLZle8WHOfSo7Xg3M+phcZfq9Fx1L6Abo+atGp7cge5pM7PjyBn4s1oZI/BRD4EMrzQBbPpVb5Q==
mri@1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a"
integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@ -6954,6 +6925,11 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
on-exit-leak-free@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209"
integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==
on-finished@^2.3.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
@ -7256,32 +7232,23 @@ pify@^5.0.0:
resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
pino-http@^5.0.1:
version "5.8.0"
resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-5.8.0.tgz#6e688fd5f965c5b6991f340eb660ea2927be9aa7"
integrity sha512-YwXiyRb9y0WCD1P9PcxuJuh3Dc5qmXde/paJE86UGYRdiFOi828hR9iUGmk5gaw6NBT9gLtKANOHFimvh19U5w==
pino-abstract-transport@v0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0"
integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==
dependencies:
duplexify "^4.1.2"
split2 "^4.0.0"
pino-http@^6.5.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-6.6.0.tgz#d0a1deacada8c93327fdaa48f5bdc94bc43d3407"
integrity sha512-PlItaK2MLpoIMLEcClhfb1VQk/o6fKppINl5s6sPE/4rvufkdO3kCSs/92EwrBsB1yssRCQqDV+w1xpYuPVnjg==
dependencies:
fast-url-parser "^1.1.3"
pino "^6.13.0"
pino-std-serializers "^4.0.0"
pino-pretty@5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-5.1.3.tgz#c4085093d1dffda359ab52731f87d96f7f832dc9"
integrity sha512-Zj+0TVdYKkAAIx9EUCL5e4TttwgsaFvJh2ceIMQeFCY8ak9tseEZQGSgpvyjEj1/iIVGIh5tdhkGEQWSMILKHA==
dependencies:
"@hapi/bourne" "^2.0.0"
args "^5.0.1"
chalk "^4.0.0"
dateformat "^4.5.1"
fast-safe-stringify "^2.0.7"
jmespath "^0.15.0"
joycon "^3.0.0"
pump "^3.0.0"
readable-stream "^3.6.0"
rfdc "^1.3.0"
split2 "^3.1.1"
strip-json-comments "^3.1.1"
get-caller-file "^2.0.5"
pino "^7.5.0"
pino-std-serializers "^5.0.0"
pino-std-serializers@^3.1.0:
version "3.2.0"
@ -7293,7 +7260,12 @@ pino-std-serializers@^4.0.0:
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2"
integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==
pino@^6.11.2, pino@^6.13.0:
pino-std-serializers@^5.0.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-5.6.0.tgz#31b141155d6520967c5ec72944d08fb45c490fd3"
integrity sha512-VdUXCw8gO+xhir7sFuoYSjTnzB+TMDGxhAC/ph3YS3sdHnXNdsK0wMtADNUltfeGkn2KDxEM21fnjF3RwXyC8A==
pino@^6.11.2:
version "6.14.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78"
integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==
@ -7306,6 +7278,23 @@ pino@^6.11.2, pino@^6.13.0:
quick-format-unescaped "^4.0.3"
sonic-boom "^1.0.2"
pino@^7.5.0:
version "7.11.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6"
integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.0.0"
on-exit-leak-free "^0.2.0"
pino-abstract-transport v0.5.0
pino-std-serializers "^4.0.0"
process-warning "^1.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.1.0"
safe-stable-stringify "^2.1.0"
sonic-boom "^2.2.1"
thread-stream "^0.15.1"
pirates@^4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
@ -7776,7 +7765,7 @@ readable-stream@1.1.14, readable-stream@^1.0.27-1:
isarray "0.0.1"
string_decoder "~0.10.x"
"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
"readable-stream@2 || 3", readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@ -7820,6 +7809,11 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
real-require@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381"
integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==
recast@^0.11.17:
version "0.11.23"
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
@ -8078,7 +8072,7 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rfdc@^1.2.0, rfdc@^1.3.0:
rfdc@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
@ -8145,6 +8139,11 @@ safe-regex@^1.1.0:
dependencies:
ret "~0.1.10"
safe-stable-stringify@^2.1.0:
version "2.4.3"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@ -8366,6 +8365,13 @@ sonic-boom@^1.0.2:
atomic-sleep "^1.0.0"
flatstr "^1.0.12"
sonic-boom@^2.2.1:
version "2.8.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611"
integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==
dependencies:
atomic-sleep "^1.0.0"
source-map-resolve@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@ -8448,12 +8454,10 @@ split2@^2.1.0:
dependencies:
through2 "^2.0.2"
split2@^3.1.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f"
integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==
dependencies:
readable-stream "^3.0.0"
split2@^4.0.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
split@^1.0.1:
version "1.0.1"
@ -8550,6 +8554,11 @@ stream-chopper@^3.0.1:
dependencies:
readable-stream "^3.0.6"
stream-shift@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
stream-to-array@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353"
@ -8830,6 +8839,13 @@ text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
thread-stream@^0.15.1:
version "0.15.2"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4"
integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==
dependencies:
real-require "^0.1.0"
through2@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4"

View File

@ -1,8 +0,0 @@
BB_ADMIN_USER_EMAIL=qa@budibase.com
BB_ADMIN_USER_PASSWORD=budibase
COUCH_DB_URL=http://budibase:budibase@localhost:4567
COUCH_DB_USER=budibase
COUCH_DB_PASSWORD=budibase
JWT_SECRET=test
BUDIBASE_HOST=http://localhost:10000
BUDIBASE_ACCOUNTS_URL=http://localhost:10001

1
qa-core/.gitignore vendored
View File

@ -2,5 +2,4 @@ node_modules/
.env
watchtower-hook.json
dist/
.testReport.json
testResults.json

View File

@ -6,13 +6,11 @@ The QA Core API tests are a jest suite that run directly against the budibase ba
You can run the whole test suite with one command, that spins up the budibase server and runs the jest tests:
`yarn api:test`
`yarn test:ci`
## Setup Server Only
## Setup Server
You can also just stand up the budibase server alone.
`yarn api:server:setup`
You can run the local development stack by following the instructions on the main readme.
## Run Tests
@ -24,11 +22,7 @@ for watch mode, where the tests will run on every change:
`yarn test:watch`
To run tests locally against a cloud service you can use the command:
`yarn run api:test:local`
To run tests locally against a cloud service you can update the configuration inside the `.env` file and run:
To run the tests in CI, it assumes the correct environment variables are set, and the server is already running. Use the command:
`yarn run api:test:ci`
`yarn test`
To run the nightly tests against the QA environment, use the command:
`yarn run api:test:nightly`

View File

@ -1,12 +0,0 @@
version: "3.8"
services:
qa-core-couchdb:
# platform: linux/amd64
container_name: budi-couchdb-qa
restart: on-failure
image: ibmcom/couchdb3
environment:
- COUCHDB_PASSWORD=${COUCH_DB_PASSWORD}
- COUCHDB_USER=${COUCH_DB_USER}
ports:
- "4567:5984"

18
qa-core/jest.config.ts Normal file
View File

@ -0,0 +1,18 @@
import { Config } from "@jest/types"
const config: Config.InitialOptions = {
preset: "ts-jest",
setupFiles: ["./src/jest/jestSetup.ts"],
setupFilesAfterEnv: ["./src/jest/jest.extends.ts"],
testEnvironment: "node",
globalSetup: "./src/jest/globalSetup.ts",
globalTeardown: "./src/jest/globalTeardown.ts",
moduleNameMapper: {
"@budibase/types": "<rootDir>/../packages/types/src",
"@budibase/server": "<rootDir>/../packages/server/src",
"@budibase/backend-core": "<rootDir>/../packages/backend-core/src",
"@budibase/backend-core/(.*)": "<rootDir>/../packages/backend-core/$1",
},
}
export default config

View File

@ -9,46 +9,26 @@
"url": "https://github.com/Budibase/budibase.git"
},
"scripts": {
"test": "env-cmd jest --runInBand",
"test:watch": "env-cmd jest --watch",
"test:debug": "DEBUG=1 jest",
"setup": "yarn && node scripts/createEnv.js",
"test": "jest --runInBand --json --outputFile=testResults.json",
"test:watch": "yarn run test --watch",
"test:debug": "DEBUG=1 yarn run test",
"test:notify": "node scripts/testResultsWebhook",
"test:ci": "jest --runInBand --json --outputFile=testResults.json --testPathIgnorePatterns=\\\"\\/dataSources\\/\\\"",
"docker:up": "docker-compose up -d",
"docker:down": "docker-compose down",
"api:server:setup": "npm run docker:up && env-cmd ts-node ../packages/builder/ts/setup.ts",
"api:server:setup:ci": "env-cmd node ../packages/builder/setup.js",
"api:test": "jest --runInBand --json --outputFile=testResults.json",
"api:test:ci": "start-server-and-test api:server:setup:ci http://localhost:4100/builder test",
"api:test:local": "start-server-and-test api:server:setup http://localhost:4100/builder test"
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"moduleNameMapper": {
"@budibase/types": "<rootDir>/../packages/types/src",
"@budibase/server": "<rootDir>/../packages/server/src",
"@budibase/backend-core": "<rootDir>/../packages/backend-core/src",
"@budibase/backend-core/(.*)": "<rootDir>/../packages/backend-core/$1"
},
"setupFiles": [
"./scripts/jestSetup.js"
],
"setupFilesAfterEnv": [
"./src/jest.extends.ts"
]
"test:smoke": "yarn run test --testPathIgnorePatterns=\\\"\\/dataSources\\/\\\"",
"test:ci": "start-server-and-test dev:built http://localhost:4001/health test:smoke",
"dev:built": "cd ../ && yarn dev:built"
},
"devDependencies": {
"@budibase/types": "^2.3.17",
"@types/jest": "29.0.0",
"@types/node-fetch": "2.6.2",
"chance": "1.1.8",
"env-cmd": "^10.1.0",
"jest": "28.1.1",
"dotenv": "16.0.1",
"jest": "29.0.0",
"prettier": "2.7.1",
"start-server-and-test": "1.14.0",
"timekeeper": "2.2.0",
"ts-jest": "28.0.8",
"ts-jest": "29.0.0",
"ts-node": "10.8.1",
"tsconfig-paths": "4.0.0",
"typescript": "4.7.3"

View File

@ -0,0 +1,22 @@
#!/usr/bin/env node
const path = require("path")
const fs = require("fs")
function init() {
const envFilePath = path.join(process.cwd(), ".env")
if (!fs.existsSync(envFilePath)) {
const envFileJson = {
BUDIBASE_URL: "http://localhost:10000",
ACCOUNT_PORTAL_URL: "http://localhost:10001",
BB_ADMIN_USER_EMAIL: "admin",
BB_ADMIN_USER_PASSWORD: "admin",
}
let envFile = ""
Object.keys(envFileJson).forEach(key => {
envFile += `${key}=${envFileJson[key]}\n`
})
fs.writeFileSync(envFilePath, envFile)
}
}
init()

View File

@ -1,11 +0,0 @@
// mock all dates to 2020-01-01T00:00:00.000Z
// use tk.reset() to use real dates in individual tests
const MOCK_DATE = new Date("2020-01-01T00:00:00.000Z")
const tk = require("timekeeper")
tk.freeze(MOCK_DATE)
if (!process.env.DEBUG) {
global.console.log = jest.fn() // console.log are ignored in tests
}
jest.setTimeout(60000)

View File

@ -0,0 +1,16 @@
import AccountInternalAPIClient from "./AccountInternalAPIClient"
import { AccountAPI, LicenseAPI } from "./apis"
import { State } from "../../types"
export default class AccountInternalAPI {
client: AccountInternalAPIClient
accounts: AccountAPI
licenses: LicenseAPI
constructor(state: State) {
this.client = new AccountInternalAPIClient(state)
this.accounts = new AccountAPI(this.client)
this.licenses = new LicenseAPI(this.client)
}
}

View File

@ -0,0 +1,70 @@
import env from "../../environment"
import fetch, { HeadersInit } from "node-fetch"
import { State } from "../../types"
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
interface ApiOptions {
method?: APIMethod
body?: object
headers?: HeadersInit | undefined
}
export default class AccountInternalAPIClient {
state: State
host: string
constructor(state: State) {
if (!env.ACCOUNT_PORTAL_URL) {
throw new Error("Must set ACCOUNT_PORTAL_URL env var")
}
this.host = `${env.ACCOUNT_PORTAL_URL}`
this.state = state
}
apiCall =
(method: APIMethod) =>
async (url = "", options: ApiOptions = {}) => {
const requestOptions = {
method,
body: JSON.stringify(options.body),
headers: {
"Content-Type": "application/json",
Accept: "application/json",
cookie: this.state.cookie,
redirect: "follow",
follow: 20,
...options.headers,
},
credentials: "include",
}
// @ts-ignore
const response = await fetch(`${this.host}${url}`, requestOptions)
let body: any
const contentType = response.headers.get("content-type")
if (contentType && contentType.includes("application/json")) {
body = await response.json()
} else {
body = await response.text()
}
const message = `${method} ${url} - ${response.status}
Response body: ${JSON.stringify(body)}
Request body: ${requestOptions.body}`
if (response.status > 499) {
console.error(message)
} else if (response.status >= 400) {
console.warn(message)
}
return [response, body]
}
post = this.apiCall("POST")
get = this.apiCall("GET")
patch = this.apiCall("PATCH")
del = this.apiCall("DELETE")
put = this.apiCall("PUT")
}

View File

@ -0,0 +1,61 @@
import { Response } from "node-fetch"
import { Account, CreateAccountRequest } from "@budibase/types"
import AccountInternalAPIClient from "../AccountInternalAPIClient"
import { APIRequestOpts } from "../../../types"
export default class AccountAPI {
client: AccountInternalAPIClient
constructor(client: AccountInternalAPIClient) {
this.client = client
}
async validateEmail(
email: string,
opts: APIRequestOpts = { doExpect: true }
): Promise<Response> {
const [response, json] = await this.client.post(
`/api/accounts/validate/email`,
{
body: { email },
}
)
if (opts.doExpect) {
expect(response).toHaveStatusCode(200)
}
return response
}
async validateTenantId(
tenantId: string,
opts: APIRequestOpts = { doExpect: true }
): Promise<Response> {
const [response, json] = await this.client.post(
`/api/accounts/validate/tenantId`,
{
body: { tenantId },
}
)
if (opts.doExpect) {
expect(response).toHaveStatusCode(200)
}
return response
}
async create(
body: CreateAccountRequest,
opts: APIRequestOpts = { doExpect: true }
): Promise<[Response, Account]> {
const headers = {
"no-verify": "1",
}
const [response, json] = await this.client.post(`/api/accounts`, {
body,
headers,
})
if (opts.doExpect) {
expect(response).toHaveStatusCode(201)
}
return [response, json]
}
}

View File

@ -0,0 +1,9 @@
import AccountInternalAPIClient from "../AccountInternalAPIClient"
export default class LicenseAPI {
client: AccountInternalAPIClient
constructor(client: AccountInternalAPIClient) {
this.client = client
}
}

View File

@ -0,0 +1,2 @@
export { default as AccountAPI } from "./AccountAPI"
export { default as LicenseAPI } from "./LicenseAPI"

View File

@ -0,0 +1 @@
export { default as AccountInternalAPI } from "./AccountInternalAPI"

View File

@ -0,0 +1 @@
export * from "./api"

View File

@ -1,73 +0,0 @@
import env from "../../../environment"
import fetch, { HeadersInit } from "node-fetch"
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
interface ApiOptions {
method?: APIMethod
body?: object
headers?: HeadersInit | undefined
}
class InternalAPIClient {
host: string
tenantName?: string
appId?: string
cookie?: string
constructor(appId?: string) {
if (!env.BUDIBASE_HOST) {
throw new Error("Must set BUDIBASE_HOST env var")
}
this.host = `${env.BUDIBASE_HOST}/api`
this.appId = appId
}
setTenantName(tenantName: string) {
this.tenantName = tenantName
}
apiCall =
(method: APIMethod) =>
async (url = "", options: ApiOptions = {}) => {
const requestOptions = {
method,
body: JSON.stringify(options.body),
headers: {
"x-budibase-app-id": this.appId,
"Content-Type": "application/json",
Accept: "application/json",
cookie: this.cookie,
redirect: "follow",
follow: 20,
...options.headers,
},
credentials: "include",
}
// prettier-ignore
// @ts-ignore
const response = await fetch(`https://${process.env.TENANT_ID}.${this.host}${url}`, requestOptions)
if (
response.status == 404 ||
response.status == 500 ||
response.status == 403
) {
console.error("Error in apiCall")
console.error("Response:", response)
const json = await response.json()
console.error("Response body:", json)
console.error("Request body:", requestOptions.body)
}
return response
}
post = this.apiCall("POST")
get = this.apiCall("GET")
patch = this.apiCall("PATCH")
del = this.apiCall("DELETE")
put = this.apiCall("PUT")
}
export default InternalAPIClient

View File

@ -1,38 +0,0 @@
import { Response } from "node-fetch"
import { Account } from "@budibase/types"
import AccountsAPIClient from "./accountsAPIClient"
import { NewAccount } from "../fixtures/types/newAccount"
export default class AccountsApi {
api: AccountsAPIClient
constructor(AccountsAPIClient: AccountsAPIClient) {
this.api = AccountsAPIClient
}
async validateEmail(email: string): Promise<Response> {
const response = await this.api.post(`/accounts/validate/email`, {
body: { email },
})
expect(response).toHaveStatusCode(200)
return response
}
async validateTenantId(tenantId: string): Promise<Response> {
const response = await this.api.post(`/accounts/validate/tenantId`, {
body: { tenantId },
})
expect(response).toHaveStatusCode(200)
return response
}
async create(body: Partial<NewAccount>): Promise<[Response, Account]> {
const headers = {
"no-verify": "1",
}
const response = await this.api.post(`/accounts`, { body, headers })
const json = await response.json()
expect(response).toHaveStatusCode(201)
return [response, json]
}
}

View File

@ -1,62 +0,0 @@
import env from "../../../environment"
import fetch, { HeadersInit } from "node-fetch"
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
interface ApiOptions {
method?: APIMethod
body?: object
headers?: HeadersInit | undefined
}
class AccountsAPIClient {
host: string
appId?: string
cookie?: string
constructor(appId?: string) {
if (!env.BUDIBASE_ACCOUNTS_URL) {
throw new Error("Must set BUDIBASE_ACCOUNTS_URL env var")
}
this.host = `${env.BUDIBASE_ACCOUNTS_URL}/api`
this.appId = appId
}
apiCall =
(method: APIMethod) =>
async (url = "", options: ApiOptions = {}) => {
const requestOptions = {
method,
body: JSON.stringify(options.body),
headers: {
"x-budibase-app-id": this.appId,
"Content-Type": "application/json",
Accept: "application/json",
cookie: this.cookie,
redirect: "follow",
follow: 20,
...options.headers,
},
credentials: "include",
}
// @ts-ignore
const response = await fetch(`${this.host}${url}`, requestOptions)
if (response.status == 404 || response.status == 500) {
console.error("Error in apiCall")
console.error("Response:", response)
const json = await response.json()
console.error("Response body:", json)
console.error("Request body:", requestOptions.body)
}
return response
}
post = this.apiCall("POST")
get = this.apiCall("GET")
patch = this.apiCall("PATCH")
del = this.apiCall("DELETE")
put = this.apiCall("PUT")
}
export default AccountsAPIClient

View File

@ -1,178 +0,0 @@
import { Application } from "@budibase/server/api/controllers/public/mapping/types"
import { App } from "@budibase/types"
import { Response } from "node-fetch"
import InternalAPIClient from "./InternalAPIClient"
import { RouteConfig } from "../fixtures/types/routing"
import { AppPackageResponse } from "../fixtures/types/appPackage"
import { DeployConfig } from "../fixtures/types/deploy"
import { responseMessage } from "../fixtures/types/responseMessage"
import { UnpublishAppResponse } from "../fixtures/types/unpublishAppResponse"
export default class AppApi {
api: InternalAPIClient
constructor(apiClient: InternalAPIClient) {
this.api = apiClient
}
// TODO Fix the fetch apps to receive an optional number of apps and compare if the received app is more or less.
// each possible scenario should have its own method.
async fetchEmptyAppList(): Promise<[Response, Application[]]> {
const response = await this.api.get(`/applications?status=all`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.length).toBeGreaterThanOrEqual(0)
return [response, json]
}
async fetchAllApplications(): Promise<[Response, Application[]]> {
const response = await this.api.get(`/applications?status=all`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.length).toBeGreaterThanOrEqual(1)
return [response, json]
}
async canRender(): Promise<[Response, boolean]> {
const response = await this.api.get("/routing/client")
expect(response).toHaveStatusCode(200)
const json = await response.json()
const publishedAppRenders = Object.keys(json.routes).length > 0
expect(publishedAppRenders).toBe(true)
return [response, publishedAppRenders]
}
async getAppPackage(appId: string): Promise<[Response, AppPackageResponse]> {
const response = await this.api.get(`/applications/${appId}/appPackage`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.application.appId).toEqual(appId)
return [response, json]
}
async publish(appId: string | undefined): Promise<[Response, DeployConfig]> {
const response = await this.api.post(`/applications/${appId}/publish`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
return [response, json]
}
async create(body: any): Promise<Partial<App>> {
const response = await this.api.post(`/applications`, { body })
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json._id).toBeDefined()
return json
}
async read(id: string): Promise<[Response, Application]> {
const response = await this.api.get(`/applications/${id}`)
const json = await response.json()
return [response, json.data]
}
async sync(appId: string): Promise<[Response, responseMessage]> {
const response = await this.api.post(`/applications/${appId}/sync`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
return [response, json]
}
// TODO
async updateClient(
appId: string,
body: any
): Promise<[Response, Application]> {
const response = await this.api.put(
`/applications/${appId}/client/update`,
{ body }
)
const json = await response.json()
return [response, json]
}
async revertPublished(appId: string): Promise<[Response, responseMessage]> {
const response = await this.api.post(`/dev/${appId}/revert`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json).toEqual({
message: "Reverted changes successfully.",
})
return [response, json]
}
async revertUnpublished(appId: string): Promise<[Response, responseMessage]> {
const response = await this.api.post(`/dev/${appId}/revert`)
const json = await response.json()
expect(response).toHaveStatusCode(400)
expect(json).toEqual({
message: "App has not yet been deployed",
status: 400,
})
return [response, json]
}
async delete(appId: string): Promise<Response> {
const response = await this.api.del(`/applications/${appId}`)
expect(response).toHaveStatusCode(200)
return response
}
async rename(
appId: string,
oldName: string,
body: any
): Promise<[Response, Application]> {
const response = await this.api.put(`/applications/${appId}`, { body })
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.name).not.toEqual(oldName)
return [response, json]
}
async addScreentoApp(body: any): Promise<[Response, Application]> {
const response = await this.api.post(`/screens`, { body })
const json = await response.json()
return [response, json]
}
async getRoutes(screenExists?: boolean): Promise<[Response, RouteConfig]> {
const response = await this.api.get(`/routing`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
if (screenExists) {
expect(json.routes["/test"]).toBeTruthy()
} else {
expect(json.routes["/test"]).toBeUndefined()
}
return [response, json]
}
async unpublish(appId: string): Promise<[Response]> {
const response = await this.api.post(`/applications/${appId}/unpublish`)
expect(response).toHaveStatusCode(204)
return [response]
}
async unlock(appId: string): Promise<[Response, responseMessage]> {
const response = await this.api.del(`/dev/${appId}/lock`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.message).toEqual("Lock released successfully.")
return [response, json]
}
async updateIcon(appId: string): Promise<[Response, Application]> {
const body = {
icon: {
name: "ConversionFunnel",
color: "var(--spectrum-global-color-red-400)",
},
}
const response = await this.api.put(`/applications/${appId}`, { body })
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.icon.name).toEqual(body.icon.name)
expect(json.icon.color).toEqual(body.icon.color)
return [response, json]
}
}

View File

@ -1,39 +0,0 @@
import { Response } from "node-fetch"
import InternalAPIClient from "./InternalAPIClient"
export default class AuthApi {
api: InternalAPIClient
constructor(apiClient: InternalAPIClient) {
this.api = apiClient
}
async loginAsAdmin(): Promise<[Response, any]> {
const response = await this.api.post(`/global/auth/default/login`, {
body: {
username: process.env.BB_ADMIN_USER_EMAIL,
password: process.env.BB_ADMIN_USER_PASSWORD,
},
})
const cookie = response.headers.get("set-cookie")
this.api.cookie = cookie as any
return [response, cookie]
}
async login(email: String, password: String): Promise<[Response, any]> {
const response = await this.api.post(`/global/auth/default/login`, {
body: {
username: email,
password: password,
},
})
expect(response).toHaveStatusCode(200)
const cookie = response.headers.get("set-cookie")
this.api.cookie = cookie as any
return [response, cookie]
}
async logout(): Promise<any> {
return this.api.post(`/global/auth/logout`)
}
}

View File

@ -1,3 +0,0 @@
const Chance = require("chance")
export default new Chance()

View File

@ -1,79 +0,0 @@
import ApplicationApi from "./applications"
import AuthApi from "./auth"
import InternalAPIClient from "./InternalAPIClient"
import AccountsApiClient from "./accountsAPIClient"
import TablesApi from "./tables"
import RowApi from "./rows"
import ScreenApi from "./screens"
import UserManagementApi from "./userManagement"
import AccountsApi from "./accounts"
import { generateAccount } from "../fixtures/accounts"
export default class TestConfiguration<T> {
applications: ApplicationApi
auth: AuthApi
screen: ScreenApi
context: T
tables: TablesApi
rows: RowApi
users: UserManagementApi
accounts: AccountsApi
apiClient: InternalAPIClient
accountsApiClient: AccountsApiClient
constructor(
apiClient: InternalAPIClient,
accountsApiClient: AccountsApiClient
) {
this.apiClient = apiClient
this.accountsApiClient = accountsApiClient
this.applications = new ApplicationApi(this.apiClient)
this.tables = new TablesApi(this.apiClient)
this.rows = new RowApi(this.apiClient)
this.auth = new AuthApi(this.apiClient)
this.screen = new ScreenApi(this.apiClient)
this.users = new UserManagementApi(this.apiClient)
this.accounts = new AccountsApi(this.accountsApiClient)
this.context = <T>{}
}
async loginAsAdmin() {
await this.auth.login(
<string>process.env.BB_ADMIN_USER_EMAIL,
<string>process.env.BB_ADMIN_USER_PASSWORD
)
}
// TODO: add logic to setup or login based in env variables
async setupAccountAndTenant() {
const account = generateAccount()
await this.accounts.validateEmail(<string>account.email)
await this.accounts.validateTenantId(<string>account.tenantId)
process.env.TENANT_ID = <string>account.tenantId
await this.accounts.create(account)
await this.updateApiClients(<string>account.tenantName)
await this.auth.login(<string>account.email, <string>account.password)
}
async updateApiClients(tenantName: string) {
this.apiClient.setTenantName(tenantName)
this.applications = new ApplicationApi(this.apiClient)
this.tables = new TablesApi(this.apiClient)
this.rows = new RowApi(this.apiClient)
this.auth = new AuthApi(this.apiClient)
this.screen = new ScreenApi(this.apiClient)
this.users = new UserManagementApi(this.apiClient)
this.context = <T>{}
}
async login(email: string, password: string) {
await this.auth.logout()
await this.auth.login(email, password)
}
async afterAll() {
this.context = <T>{}
await this.auth.logout()
}
}

View File

@ -1,22 +0,0 @@
import { NewAccount } from "./types/newAccount"
import generator from "../../generator"
import { Hosting } from "@budibase/types"
export const generateAccount = (): Partial<NewAccount> => {
const randomGuid = generator.guid()
//Needs to start with a letter
let tenant: string = "tenant" + randomGuid
tenant = tenant.replace(/-/g, "")
return {
email: `qa+${randomGuid}@budibase.com`,
hosting: Hosting.CLOUD,
name: `qa+${randomGuid}@budibase.com`,
password: `${randomGuid}`,
profession: "software_engineer",
size: "10+",
tenantId: `${tenant}`,
tenantName: `${tenant}`,
}
}

View File

@ -1,3 +0,0 @@
export interface responseMessage {
message: string
}

View File

@ -1,77 +0,0 @@
import env from "../../../environment"
import fetch, { HeadersInit } from "node-fetch"
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
interface ApiOptions {
method?: APIMethod
body?: object
headers?: HeadersInit | undefined
}
class PublicAPIClient {
host: string
apiKey?: string
tenantName?: string
appId?: string
cookie?: string
constructor(appId?: string) {
if (!env.BUDIBASE_HOST) {
throw new Error("Must set BUDIBASE_HOST env var")
}
this.host = `${env.BUDIBASE_HOST}/api/public/v1`
this.appId = appId
}
setTenantName(tenantName: string) {
this.tenantName = tenantName
}
setApiKey(apiKey: string) {
this.apiKey = apiKey
process.env.BUDIBASE_PUBLIC_API_KEY = apiKey
this.host = `${env.BUDIBASE_HOST}/api/public/v1`
}
apiCall =
(method: APIMethod) =>
async (url = "", options: ApiOptions = {}) => {
const requestOptions = {
method,
body: JSON.stringify(options.body),
headers: {
"x-budibase-api-key": this.apiKey || null,
"x-budibase-app-id": this.appId,
"Content-Type": "application/json",
Accept: "application/json",
...options.headers,
cookie: this.cookie,
redirect: "follow",
follow: 20,
},
}
// prettier-ignore
// @ts-ignore
const response = await fetch(`https://${process.env.TENANT_ID}.${this.host}${url}`, requestOptions)
if (response.status == 500 || response.status == 403) {
console.error("Error in apiCall")
console.error("Response:", response)
const json = await response.json()
console.error("Response body:", json)
console.error("Request body:", requestOptions.body)
}
return response
}
post = this.apiCall("POST")
get = this.apiCall("GET")
patch = this.apiCall("PATCH")
del = this.apiCall("DELETE")
put = this.apiCall("PUT")
}
export default PublicAPIClient

View File

@ -1,38 +0,0 @@
import { Response } from "node-fetch"
import { Account } from "@budibase/types"
import AccountsAPIClient from "./accountsAPIClient"
import { NewAccount } from "../fixtures/types/newAccount"
export default class AccountsApi {
api: AccountsAPIClient
constructor(AccountsAPIClient: AccountsAPIClient) {
this.api = AccountsAPIClient
}
async validateEmail(email: string): Promise<Response> {
const response = await this.api.post(`/accounts/validate/email`, {
body: { email },
})
expect(response).toHaveStatusCode(200)
return response
}
async validateTenantId(tenantId: string): Promise<Response> {
const response = await this.api.post(`/accounts/validate/tenantId`, {
body: { tenantId },
})
expect(response).toHaveStatusCode(200)
return response
}
async create(body: Partial<NewAccount>): Promise<[Response, Account]> {
const headers = {
"no-verify": "1",
}
const response = await this.api.post(`/accounts`, { body, headers })
const json = await response.json()
expect(response).toHaveStatusCode(201)
return [response, json]
}
}

View File

@ -1,66 +0,0 @@
import env from "../../../environment"
import fetch, { HeadersInit } from "node-fetch"
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
interface ApiOptions {
method?: APIMethod
body?: object
headers?: HeadersInit | undefined
}
class AccountsAPIClient {
host: string
appId?: string
cookie?: string
constructor(appId?: string) {
if (!env.BUDIBASE_ACCOUNTS_URL) {
throw new Error("Must set BUDIBASE_ACCOUNTS_URL env var")
}
this.host = `${env.BUDIBASE_ACCOUNTS_URL}/api`
this.appId = appId
}
apiCall =
(method: APIMethod) =>
async (url = "", options: ApiOptions = {}) => {
const requestOptions = {
method,
body: JSON.stringify(options.body),
headers: {
"x-budibase-app-id": this.appId,
"Content-Type": "application/json",
Accept: "application/json",
cookie: this.cookie,
redirect: "follow",
follow: 20,
...options.headers,
},
credentials: "include",
}
// @ts-ignore
const response = await fetch(`${this.host}${url}`, requestOptions)
if (
response.status == 404 ||
response.status == 500 ||
response.status == 400
) {
console.error("Error in apiCall")
console.error("Response:", response)
const json = await response.json()
console.error("Response body:", json)
console.error("Request body:", requestOptions.body)
}
return response
}
post = this.apiCall("POST")
get = this.apiCall("GET")
patch = this.apiCall("PATCH")
del = this.apiCall("DELETE")
put = this.apiCall("PUT")
}
export default AccountsAPIClient

Some files were not shown because too many files have changed in this diff Show More