Budibase is an open-source low-code platform for creating internal apps in minutes. Supports PostgreSQL, MySQL, MSSQL, MongoDB, Rest API, Docker, K8s 🚀
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

94 lines
3.1 KiB

const CouchDB = require("../index")
const Sentry = require("@sentry/node")
/**
* Only needed so that boolean parameters are being used for includeDocs
* @type {{EXCLUDE: boolean, INCLUDE: boolean}}
*/
exports.IncludeDocs = {
INCLUDE: true,
EXCLUDE: false,
}
/**
* Creates the link view for the instance, this will overwrite the existing one, but this should only
* be called if it is found that the view does not exist.
* @param {string} instanceId The instance to which the view should be added.
* @returns {Promise<void>} The view now exists, please note that the next view of this query will actually build it,
* so it may be slow.
*/
exports.createLinkView = async instanceId => {
const db = new CouchDB(instanceId)
const designDoc = await db.get("_design/database")
const view = {
map: function(doc) {
if (doc.type === "link") {
let doc1 = doc.doc1
let doc2 = doc.doc2
emit([doc1.modelId, doc1.recordId], {
id: doc2.recordId,
thisId: doc1.recordId,
fieldName: doc1.fieldName,
})
emit([doc2.modelId, doc2.recordId], {
id: doc1.recordId,
thisId: doc2.recordId,
fieldName: doc2.fieldName,
})
}
}.toString(),
}
designDoc.views = {
...designDoc.views,
by_link: view,
}
await db.put(designDoc)
}
/**
* Gets the linking documents, not the linked documents themselves.
* @param {string} instanceId The instance in which we are searching for linked records.
* @param {string} modelId The model which we are searching for linked records against.
* @param {string|null} fieldName The name of column/field which is being altered, only looking for
* linking documents that are related to it. If this is not specified then the table level will be assumed.
* @param {string|null} recordId The ID of the record which we want to find linking documents for -
* if this is not specified then it will assume model or field level depending on whether the
* field name has been specified.
* @param {boolean|null} includeDocs whether to include docs in the response call, this is considerably slower so only
* use this if actually interested in the docs themselves.
* @returns {Promise<object[]>} This will return an array of the linking documents that were found
* (if any).
*/
exports.getLinkDocuments = async function({
instanceId,
modelId,
recordId,
includeDocs,
}) {
const db = new CouchDB(instanceId)
let params
if (recordId != null) {
params = { key: [modelId, recordId] }
}
// only model is known
else {
params = { startKey: [modelId], endKey: [modelId, {}] }
}
params.include_docs = !!includeDocs
try {
const response = await db.query("database/by_link", params)
if (includeDocs) {
return response.rows.map(row => row.doc)
} else {
return response.rows.map(row => row.value)
}
} catch (err) {
// check if the view doesn't exist, it should for all new instances
if (err != null && err.name === "not_found") {
await exports.createLinkView(instanceId)
return exports.getLinkDocuments(arguments[0])
} else {
Sentry.captureException(err)
}
}
}