Adding jsdoc to the db utils and removing the views, this is a breaking change for existing apps.

This commit is contained in:
mike12345567 2020-10-02 12:37:46 +01:00
parent c7693d6e86
commit 0db7768e5d
9 changed files with 115 additions and 52 deletions

View File

@ -1,5 +1,4 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const newid = require("../../db/newid")
const { const {
generateAdminPermissions, generateAdminPermissions,
generatePowerUserPermissions, generatePowerUserPermissions,
@ -95,7 +94,7 @@ exports.create = async function(ctx) {
name: ctx.request.body.name, name: ctx.request.body.name,
_rev: ctx.request.body._rev, _rev: ctx.request.body._rev,
permissions: ctx.request.body.permissions || [], permissions: ctx.request.body.permissions || [],
_id: generateAccessLevelID(newid()), _id: generateAccessLevelID(),
type: "accesslevel", type: "accesslevel",
} }

View File

@ -1,7 +1,6 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const ClientDb = require("../../db/clientDb") const ClientDb = require("../../db/clientDb")
const { getPackageForBuilder, buildPage } = require("../../utilities/builder") const { getPackageForBuilder, buildPage } = require("../../utilities/builder")
const newid = require("../../db/newid")
const env = require("../../environment") const env = require("../../environment")
const instanceController = require("./instance") const instanceController = require("./instance")
const { resolve, join } = require("path") const { resolve, join } = require("path")
@ -49,7 +48,7 @@ exports.create = async function(ctx) {
if (!clientId) { if (!clientId) {
ctx.throw(400, "ClientId not suplied") ctx.throw(400, "ClientId not suplied")
} }
const appId = generateAppID(newid()) const appId = generateAppID()
// insert an appId -> clientId lookup // insert an appId -> clientId lookup
const masterDb = new CouchDB("client_app_lookup") const masterDb = new CouchDB("client_app_lookup")

View File

@ -1,5 +1,4 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const newid = require("../../db/newid")
const actions = require("../../automations/actions") const actions = require("../../automations/actions")
const logic = require("../../automations/logic") const logic = require("../../automations/logic")
const triggers = require("../../automations/triggers") const triggers = require("../../automations/triggers")
@ -35,7 +34,7 @@ exports.create = async function(ctx) {
const db = new CouchDB(ctx.user.instanceId) const db = new CouchDB(ctx.user.instanceId)
let automation = ctx.request.body let automation = ctx.request.body
automation._id = generateAutomationID(newid()) automation._id = generateAutomationID()
automation.type = "automation" automation.type = "automation"
automation = cleanAutomationInputs(automation) automation = cleanAutomationInputs(automation)

View File

@ -1,5 +1,4 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const newid = require("../../db/newid")
const { const {
getRecordParams, getRecordParams,
getModelParams, getModelParams,
@ -25,7 +24,7 @@ exports.save = async function(ctx) {
const db = new CouchDB(ctx.user.instanceId) const db = new CouchDB(ctx.user.instanceId)
const modelToSave = { const modelToSave = {
type: "model", type: "model",
_id: generateModelID(newid()), _id: generateModelID(),
views: {}, views: {},
...ctx.request.body, ...ctx.request.body,
} }

View File

@ -1,6 +1,5 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const validateJs = require("validate.js") const validateJs = require("validate.js")
const newid = require("../../db/newid")
const { getRecordParams, generateRecordID } = require("../../db/utils") const { getRecordParams, generateRecordID } = require("../../db/utils")
const MODEL_VIEW_BEGINS_WITH = "all_model:" const MODEL_VIEW_BEGINS_WITH = "all_model:"
@ -69,7 +68,7 @@ exports.save = async function(ctx) {
record.modelId = ctx.params.modelId record.modelId = ctx.params.modelId
if (!record._rev && !record._id) { if (!record._rev && !record._id) {
record._id = generateRecordID(record.modelId, newid()) record._id = generateRecordID(record.modelId)
} }
const model = await db.get(record.modelId) const model = await db.get(record.modelId)

View File

@ -1,7 +1,7 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const clientDb = require("../../db/clientDb") const clientDb = require("../../db/clientDb")
const bcrypt = require("../../utilities/bcrypt") const bcrypt = require("../../utilities/bcrypt")
const getUserId = userName => `user_${userName}` const { generateUserID, getUserParams } = require("../../db/utils")
const { const {
POWERUSER_LEVEL_ID, POWERUSER_LEVEL_ID,
ADMIN_LEVEL_ID, ADMIN_LEVEL_ID,
@ -9,11 +9,11 @@ const {
exports.fetch = async function(ctx) { exports.fetch = async function(ctx) {
const database = new CouchDB(ctx.user.instanceId) const database = new CouchDB(ctx.user.instanceId)
const data = await database.query("database/by_type", { const data = await database.allDocs(
include_docs: true, getUserParams(null, {
key: ["user"], include_docs: true,
}) })
)
ctx.body = data.rows.map(row => row.doc) ctx.body = data.rows.map(row => row.doc)
} }
@ -31,7 +31,7 @@ exports.create = async function(ctx) {
if (!accessLevel) ctx.throw(400, "Invalid Access Level") if (!accessLevel) ctx.throw(400, "Invalid Access Level")
const user = { const user = {
_id: getUserId(username), _id: generateUserID(username),
username, username,
password: await bcrypt.hash(password), password: await bcrypt.hash(password),
name: name || username, name: name || username,
@ -80,14 +80,14 @@ exports.update = async function(ctx) {
exports.destroy = async function(ctx) { exports.destroy = async function(ctx) {
const database = new CouchDB(ctx.user.instanceId) const database = new CouchDB(ctx.user.instanceId)
await database.destroy(getUserId(ctx.params.username)) await database.destroy(generateUserID(ctx.params.username))
ctx.message = `User ${ctx.params.username} deleted.` ctx.message = `User ${ctx.params.username} deleted.`
ctx.status = 200 ctx.status = 200
} }
exports.find = async function(ctx) { exports.find = async function(ctx) {
const database = new CouchDB(ctx.user.instanceId) const database = new CouchDB(ctx.user.instanceId)
const user = await database.get(getUserId(ctx.params.username)) const user = await database.get(generateUserID(ctx.params.username))
ctx.body = { ctx.body = {
username: user.username, username: user.username,
name: user.name, name: user.name,

View File

@ -11,18 +11,11 @@ const controller = {
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
const response = [] const response = []
for (let name in designDoc.views) { for (let name of Object.keys(designDoc.views)) {
if ( response.push({
!name.startsWith("all") && name,
name !== "by_type" && ...designDoc.views[name],
name !== "by_username" && })
name !== "by_automation_trigger"
) {
response.push({
name,
...designDoc.views[name],
})
}
} }
ctx.body = response ctx.body = response

View File

@ -90,11 +90,18 @@ async function queueRelevantRecordAutomations(event, eventType) {
throw `No instanceId specified for ${eventType} - check event emitters.` throw `No instanceId specified for ${eventType} - check event emitters.`
} }
const db = new CouchDB(event.instanceId) const db = new CouchDB(event.instanceId)
const automationsToTrigger = await db.allDocs( let automations = await db.allDocs(
getAutomationParams(null, { include_docs: true }) getAutomationParams(null, { include_docs: true })
) )
const automations = automationsToTrigger.rows.map(wf => wf.doc) // filter down to the correct event type
automations = automations.rows
.map(automation => automation.doc)
.filter(automation => {
const trigger = automation.definition.trigger
return trigger && trigger.event === eventType
})
for (let automation of automations) { for (let automation of automations) {
let automationDef = automation.definition let automationDef = automation.definition
let automationTrigger = automationDef ? automationDef.trigger : {} let automationTrigger = automationDef ? automationDef.trigger : {}

View File

@ -1,3 +1,5 @@
const newid = require("./newid")
const DocumentTypes = { const DocumentTypes = {
MODEL: "model", MODEL: "model",
RECORD: "record", RECORD: "record",
@ -12,6 +14,15 @@ exports.DocumentTypes = DocumentTypes
const UNICODE_MAX = "\ufff0" const UNICODE_MAX = "\ufff0"
/**
* If creating DB allDocs/query params with only a single input this can be used, this
* is usually the case for top level documents like models, automations, users etc.
* @param {string} docType The type of document which input params are being built for, e.g. user,
* link, app, model and so on.
* @param {string|null} input The input if looking for a particular entry.
* @param {object} otherProps Add any other properties onto the request, e.g. include_docs.
* @returns {object} Parameters which can then be used with an allDocs request.
*/
function singleInputParams(docType, input, otherProps = {}) { function singleInputParams(docType, input, otherProps = {}) {
if (input == null) { if (input == null) {
input = "" input = ""
@ -23,17 +34,32 @@ function singleInputParams(docType, input, otherProps = {}) {
} }
} }
exports.getModelParams = (modelId, otherProps = {}) => { /**
* Gets parameters for retrieving models, this is a utility function for the singleInputParams function.
*/
exports.getModelParams = (modelId = null, otherProps = {}) => {
return singleInputParams(DocumentTypes.MODEL, modelId, otherProps) return singleInputParams(DocumentTypes.MODEL, modelId, otherProps)
} }
exports.generateModelID = modelId => { /**
return `${DocumentTypes.MODEL}:${modelId}` * Generates a new model ID.
* @returns {string} The new model ID which the model doc can be stored under.
*/
exports.generateModelID = () => {
return `${DocumentTypes.MODEL}:${newid()}`
} }
exports.getRecordParams = (modelId, recordId, otherProps = {}) => { /**
if (modelId == null && recordId != null) { * Gets the DB allDocs/query params for retrieving a record.
throw "Cannot build key for record ID without a model ID" * @param {string} modelId The model in which the records have been stored.
* @param {string|null} recordId The ID of the record which is being specifically queried for. This can be
* left null to get all the records in the model.
* @param {object} otherProps Any other properties to add to the request.
* @returns {object} Parameters which can then be used with an allDocs request.
*/
exports.getRecordParams = (modelId, recordId = null, otherProps = {}) => {
if (modelId == null) {
throw "Cannot build params for records without a model ID"
} }
const endOfKey = recordId == null ? `${modelId}:` : `${modelId}:${recordId}` const endOfKey = recordId == null ? `${modelId}:` : `${modelId}:${recordId}`
return { return {
@ -43,44 +69,86 @@ exports.getRecordParams = (modelId, recordId, otherProps = {}) => {
} }
} }
exports.generateRecordID = (modelId, recordId) => { /**
return `${DocumentTypes.RECORD}:${modelId}:${recordId}` * Gets a new record ID for the specified model.
* @param {string} modelId The model which the record is being created for.
* @returns {string} The new ID which a record doc can be stored under.
*/
exports.generateRecordID = modelId => {
return `${DocumentTypes.RECORD}:${modelId}:${newid()}`
} }
exports.getUserParams = (username, otherProps = {}) => { /**
* Gets parameters for retrieving users, this is a utility function for the singleInputParams function.
*/
exports.getUserParams = (username = null, otherProps = {}) => {
return singleInputParams(DocumentTypes.USER, username, otherProps) return singleInputParams(DocumentTypes.USER, username, otherProps)
} }
/**
* Generates a new user ID based on the passed in username.
* @param {string} username The username which the ID is going to be built up of.
* @returns {string} The new user ID which the user doc can be stored under.
*/
exports.generateUserID = username => { exports.generateUserID = username => {
return `${DocumentTypes.USER}:${username}` return `${DocumentTypes.USER}:${username}`
} }
exports.getAutomationParams = (automationId, otherProps = {}) => { /**
* Gets parameters for retrieving automations, this is a utility function for the singleInputParams function.
*/
exports.getAutomationParams = (automationId = null, otherProps = {}) => {
return singleInputParams(DocumentTypes.AUTOMATION, automationId, otherProps) return singleInputParams(DocumentTypes.AUTOMATION, automationId, otherProps)
} }
exports.generateAutomationID = automationId => { /**
return `${DocumentTypes.AUTOMATION}:${automationId}` * Generates a new automation ID.
* @returns {string} The new automation ID which the automation doc can be stored under.
*/
exports.generateAutomationID = () => {
return `${DocumentTypes.AUTOMATION}:${newid()}`
} }
// for now link records still have their own view as we can walk multiple directions /**
* Generates a new link doc ID. This is currently not usable with the alldocs call,
* instead a view is built to make walking to tree easier.
* @param {string} modelId1 The ID of the linker model.
* @param {string} modelId2 The ID of the linked model.
* @param {string} recordId1 The ID of the linker record.
* @param {string} recordId2 The ID of the linked record.
* @returns {string} The new link doc ID which the automation doc can be stored under.
*/
exports.generateLinkID = (modelId1, modelId2, recordId1, recordId2) => { exports.generateLinkID = (modelId1, modelId2, recordId1, recordId2) => {
return `${DocumentTypes.AUTOMATION}:${modelId1}:${modelId2}:${recordId1}:${recordId2}` return `${DocumentTypes.AUTOMATION}:${modelId1}:${modelId2}:${recordId1}:${recordId2}`
} }
exports.generateAppID = appId => { /**
return `${DocumentTypes.APP}:${appId}` * Generates a new app ID.
* @returns {string} The new app ID which the app doc can be stored under.
*/
exports.generateAppID = () => {
return `${DocumentTypes.APP}:${newid()}`
} }
exports.getAppParams = (appId, otherProps = {}) => { /**
* Gets parameters for retrieving apps, this is a utility function for the singleInputParams function.
*/
exports.getAppParams = (appId = null, otherProps = {}) => {
return singleInputParams(DocumentTypes.APP, appId, otherProps) return singleInputParams(DocumentTypes.APP, appId, otherProps)
} }
exports.generateAccessLevelID = accessLevelId => { /**
return `${DocumentTypes.ACCESS_LEVEL}:${accessLevelId}` * Generates a new access level ID.
* @returns {string} The new access level ID which the access level doc can be stored under.
*/
exports.generateAccessLevelID = () => {
return `${DocumentTypes.ACCESS_LEVEL}:${newid()}`
} }
exports.getAccessLevelParams = (accessLevelId, otherProps) => { /**
* Gets parameters for retrieving an access level, this is a utility function for the singleInputParams function.
*/
exports.getAccessLevelParams = (accessLevelId = null, otherProps = {}) => {
return singleInputParams( return singleInputParams(
DocumentTypes.ACCESS_LEVEL, DocumentTypes.ACCESS_LEVEL,
accessLevelId, accessLevelId,