Merge branch 'master' into multistep-formblock-feedback
This commit is contained in:
commit
63e2c50a0a
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.14.6",
|
||||
"version": "2.14.7",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*",
|
||||
|
|
|
@ -19,6 +19,8 @@ import { WriteStream, ReadStream } from "fs"
|
|||
import { newid } from "../../docIds/newid"
|
||||
import { DDInstrumentedDatabase } from "../instrumentation"
|
||||
|
||||
const DATABASE_NOT_FOUND = "Database does not exist."
|
||||
|
||||
function buildNano(couchInfo: { url: string; cookie: string }) {
|
||||
return Nano({
|
||||
url: couchInfo.url,
|
||||
|
@ -31,6 +33,8 @@ function buildNano(couchInfo: { url: string; cookie: string }) {
|
|||
})
|
||||
}
|
||||
|
||||
type DBCall<T> = () => Promise<T>
|
||||
|
||||
export function DatabaseWithConnection(
|
||||
dbName: string,
|
||||
connection: string,
|
||||
|
@ -78,7 +82,11 @@ export class DatabaseImpl implements Database {
|
|||
return this.instanceNano || DatabaseImpl.nano
|
||||
}
|
||||
|
||||
async checkSetup() {
|
||||
private getDb() {
|
||||
return this.nano().db.use(this.name)
|
||||
}
|
||||
|
||||
private async checkAndCreateDb() {
|
||||
let shouldCreate = !this.pouchOpts?.skip_setup
|
||||
// check exists in a lightweight fashion
|
||||
let exists = await this.exists()
|
||||
|
@ -95,14 +103,22 @@ export class DatabaseImpl implements Database {
|
|||
}
|
||||
}
|
||||
}
|
||||
return this.nano().db.use(this.name)
|
||||
return this.getDb()
|
||||
}
|
||||
|
||||
private async updateOutput(fnc: any) {
|
||||
// this function fetches the DB and handles if DB creation is needed
|
||||
private async performCall<T>(
|
||||
call: (db: Nano.DocumentScope<any>) => Promise<DBCall<T>> | DBCall<T>
|
||||
): Promise<any> {
|
||||
const db = this.getDb()
|
||||
const fnc = await call(db)
|
||||
try {
|
||||
return await fnc()
|
||||
} catch (err: any) {
|
||||
if (err.statusCode) {
|
||||
if (err.statusCode === 404 && err.reason === DATABASE_NOT_FOUND) {
|
||||
await this.checkAndCreateDb()
|
||||
return await this.performCall(call)
|
||||
} else if (err.statusCode) {
|
||||
err.status = err.statusCode
|
||||
}
|
||||
throw err
|
||||
|
@ -110,11 +126,12 @@ export class DatabaseImpl implements Database {
|
|||
}
|
||||
|
||||
async get<T extends Document>(id?: string): Promise<T> {
|
||||
const db = await this.checkSetup()
|
||||
if (!id) {
|
||||
throw new Error("Unable to get doc without a valid _id.")
|
||||
}
|
||||
return this.updateOutput(() => db.get(id))
|
||||
return this.performCall(db => {
|
||||
if (!id) {
|
||||
throw new Error("Unable to get doc without a valid _id.")
|
||||
}
|
||||
return () => db.get(id)
|
||||
})
|
||||
}
|
||||
|
||||
async getMultiple<T extends Document>(
|
||||
|
@ -147,22 +164,23 @@ export class DatabaseImpl implements Database {
|
|||
}
|
||||
|
||||
async remove(idOrDoc: string | Document, rev?: string) {
|
||||
const db = await this.checkSetup()
|
||||
let _id: string
|
||||
let _rev: string
|
||||
return this.performCall(db => {
|
||||
let _id: string
|
||||
let _rev: string
|
||||
|
||||
if (isDocument(idOrDoc)) {
|
||||
_id = idOrDoc._id!
|
||||
_rev = idOrDoc._rev!
|
||||
} else {
|
||||
_id = idOrDoc
|
||||
_rev = rev!
|
||||
}
|
||||
if (isDocument(idOrDoc)) {
|
||||
_id = idOrDoc._id!
|
||||
_rev = idOrDoc._rev!
|
||||
} else {
|
||||
_id = idOrDoc
|
||||
_rev = rev!
|
||||
}
|
||||
|
||||
if (!_id || !_rev) {
|
||||
throw new Error("Unable to remove doc without a valid _id and _rev.")
|
||||
}
|
||||
return this.updateOutput(() => db.destroy(_id, _rev))
|
||||
if (!_id || !_rev) {
|
||||
throw new Error("Unable to remove doc without a valid _id and _rev.")
|
||||
}
|
||||
return () => db.destroy(_id, _rev)
|
||||
})
|
||||
}
|
||||
|
||||
async post(document: AnyDocument, opts?: DatabasePutOpts) {
|
||||
|
@ -176,45 +194,49 @@ export class DatabaseImpl implements Database {
|
|||
if (!document._id) {
|
||||
throw new Error("Cannot store document without _id field.")
|
||||
}
|
||||
const db = await this.checkSetup()
|
||||
if (!document.createdAt) {
|
||||
document.createdAt = new Date().toISOString()
|
||||
}
|
||||
document.updatedAt = new Date().toISOString()
|
||||
if (opts?.force && document._id) {
|
||||
try {
|
||||
const existing = await this.get(document._id)
|
||||
if (existing) {
|
||||
document._rev = existing._rev
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.status !== 404) {
|
||||
throw err
|
||||
return this.performCall(async db => {
|
||||
if (!document.createdAt) {
|
||||
document.createdAt = new Date().toISOString()
|
||||
}
|
||||
document.updatedAt = new Date().toISOString()
|
||||
if (opts?.force && document._id) {
|
||||
try {
|
||||
const existing = await this.get(document._id)
|
||||
if (existing) {
|
||||
document._rev = existing._rev
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.status !== 404) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.updateOutput(() => db.insert(document))
|
||||
return () => db.insert(document)
|
||||
})
|
||||
}
|
||||
|
||||
async bulkDocs(documents: AnyDocument[]) {
|
||||
const db = await this.checkSetup()
|
||||
return this.updateOutput(() => db.bulk({ docs: documents }))
|
||||
return this.performCall(db => {
|
||||
return () => db.bulk({ docs: documents })
|
||||
})
|
||||
}
|
||||
|
||||
async allDocs<T extends Document>(
|
||||
params: DatabaseQueryOpts
|
||||
): Promise<AllDocsResponse<T>> {
|
||||
const db = await this.checkSetup()
|
||||
return this.updateOutput(() => db.list(params))
|
||||
return this.performCall(db => {
|
||||
return () => db.list(params)
|
||||
})
|
||||
}
|
||||
|
||||
async query<T extends Document>(
|
||||
viewName: string,
|
||||
params: DatabaseQueryOpts
|
||||
): Promise<AllDocsResponse<T>> {
|
||||
const db = await this.checkSetup()
|
||||
const [database, view] = viewName.split("/")
|
||||
return this.updateOutput(() => db.view(database, view, params))
|
||||
return this.performCall(db => {
|
||||
const [database, view] = viewName.split("/")
|
||||
return () => db.view(database, view, params)
|
||||
})
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
|
@ -231,8 +253,9 @@ export class DatabaseImpl implements Database {
|
|||
}
|
||||
|
||||
async compact() {
|
||||
const db = await this.checkSetup()
|
||||
return this.updateOutput(() => db.compact())
|
||||
return this.performCall(db => {
|
||||
return () => db.compact()
|
||||
})
|
||||
}
|
||||
|
||||
// All below functions are in-frequently called, just utilise PouchDB
|
||||
|
|
|
@ -31,13 +31,6 @@ export class DDInstrumentedDatabase implements Database {
|
|||
})
|
||||
}
|
||||
|
||||
checkSetup(): Promise<DocumentScope<any>> {
|
||||
return tracer.trace("db.checkSetup", span => {
|
||||
span?.addTags({ db_name: this.name })
|
||||
return this.db.checkSetup()
|
||||
})
|
||||
}
|
||||
|
||||
get<T extends Document>(id?: string | undefined): Promise<T> {
|
||||
return tracer.trace("db.get", span => {
|
||||
span?.addTags({ db_name: this.name, doc_id: id })
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
loading = false
|
||||
}
|
||||
|
||||
async function confirm() {
|
||||
export async function confirm() {
|
||||
loading = true
|
||||
if (!onConfirm || (await onConfirm()) !== keepOpen) {
|
||||
hide()
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
const appPrefix = "/app"
|
||||
let touched = false
|
||||
let error
|
||||
let modal
|
||||
|
||||
$: appUrl = screenUrl
|
||||
? `${window.location.origin}${appPrefix}${screenUrl}`
|
||||
|
@ -50,6 +51,7 @@
|
|||
</script>
|
||||
|
||||
<ModalContent
|
||||
bind:this={modal}
|
||||
size="M"
|
||||
title={"Screen details"}
|
||||
{confirmText}
|
||||
|
@ -58,15 +60,17 @@
|
|||
cancelText={"Back"}
|
||||
disabled={!screenUrl || error || !touched}
|
||||
>
|
||||
<Input
|
||||
label="Enter a URL for the new screen"
|
||||
{error}
|
||||
bind:value={screenUrl}
|
||||
on:change={routeChanged}
|
||||
/>
|
||||
<div class="app-server" title={appUrl}>
|
||||
{appUrl}
|
||||
</div>
|
||||
<form on:submit|preventDefault={() => modal.confirm()}>
|
||||
<Input
|
||||
label="Enter a URL for the new screen"
|
||||
{error}
|
||||
bind:value={screenUrl}
|
||||
on:change={routeChanged}
|
||||
/>
|
||||
<div class="app-server" title={appUrl}>
|
||||
{appUrl}
|
||||
</div>
|
||||
</form>
|
||||
</ModalContent>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -121,7 +121,6 @@ export interface Database {
|
|||
name: string
|
||||
|
||||
exists(): Promise<boolean>
|
||||
checkSetup(): Promise<Nano.DocumentScope<any>>
|
||||
get<T extends Document>(id?: string): Promise<T>
|
||||
getMultiple<T extends Document>(
|
||||
ids: string[],
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@budibase/types": "^2.3.17",
|
||||
"@swc/core": "1.3.71",
|
||||
"@swc/jest": "0.2.27",
|
||||
"@trendyol/jest-testcontainers": "2.1.1",
|
||||
"@types/jest": "29.5.3",
|
||||
"@types/node-fetch": "2.6.4",
|
||||
|
@ -32,8 +34,6 @@
|
|||
"jest": "29.7.0",
|
||||
"prettier": "2.7.1",
|
||||
"start-server-and-test": "1.14.0",
|
||||
"@swc/core": "1.3.71",
|
||||
"@swc/jest": "0.2.27",
|
||||
"timekeeper": "2.2.0",
|
||||
"ts-jest": "29.1.1",
|
||||
"ts-node": "10.8.1",
|
||||
|
@ -43,6 +43,7 @@
|
|||
"dependencies": {
|
||||
"@budibase/backend-core": "^2.3.17",
|
||||
"form-data": "^4.0.0",
|
||||
"node-fetch": "2.6.7"
|
||||
"node-fetch": "2.6.7",
|
||||
"stripe": "^14.11.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -951,6 +951,13 @@
|
|||
resolved "https://registry.npmjs.org/@types/node/-/node-18.15.1.tgz"
|
||||
integrity sha512-U2TWca8AeHSmbpi314QBESRk7oPjSZjDsR+c+H4ECC1l+kFgpZf8Ydhv3SJpPy51VyZHHqxlb6mTTqYNNRVAIw==
|
||||
|
||||
"@types/node@>=8.1.0":
|
||||
version "20.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f"
|
||||
integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/stack-utils@^2.0.0":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz"
|
||||
|
@ -4549,6 +4556,14 @@ strip-json-comments@^3.1.1:
|
|||
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
stripe@^14.11.0:
|
||||
version "14.11.0"
|
||||
resolved "https://registry.yarnpkg.com/stripe/-/stripe-14.11.0.tgz#1df63c31bcff3b136457c2b7584f917509e8030c"
|
||||
integrity sha512-NmFEkDC0PldP7CQtdPgKs5dVZA/pF+IepldbmB+Kk9B4d7EBkWnbANp0y+/zJcbRGul48s8hmQzeqNWUlWW0wg==
|
||||
dependencies:
|
||||
"@types/node" ">=8.1.0"
|
||||
qs "^6.11.0"
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
||||
|
@ -4807,6 +4822,11 @@ uid2@0.0.x:
|
|||
resolved "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz"
|
||||
integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==
|
||||
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
|
||||
universalify@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz"
|
||||
|
|
Loading…
Reference in New Issue