mirror of https://github.com/Budibase/budibase.git
committed by
GitHub
20 changed files with 424 additions and 209 deletions
@ -0,0 +1,109 @@ |
|||||
|
const { |
||||
|
ViewNames, |
||||
|
generateMemoryViewID, |
||||
|
getMemoryViewParams, |
||||
|
} = require("../../../db/utils") |
||||
|
const env = require("../../../environment") |
||||
|
|
||||
|
exports.getView = async (db, viewName) => { |
||||
|
if (env.SELF_HOSTED) { |
||||
|
const designDoc = await db.get("_design/database") |
||||
|
return designDoc.views[viewName] |
||||
|
} else { |
||||
|
const viewDoc = await db.get(generateMemoryViewID(viewName)) |
||||
|
return viewDoc.view |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
exports.getViews = async db => { |
||||
|
const response = [] |
||||
|
if (env.SELF_HOSTED) { |
||||
|
const designDoc = await db.get("_design/database") |
||||
|
for (let name of Object.keys(designDoc.views)) { |
||||
|
// Only return custom views, not built ins
|
||||
|
if (Object.values(ViewNames).indexOf(name) !== -1) { |
||||
|
continue |
||||
|
} |
||||
|
response.push({ |
||||
|
name, |
||||
|
...designDoc.views[name], |
||||
|
}) |
||||
|
} |
||||
|
} else { |
||||
|
const views = ( |
||||
|
await db.allDocs( |
||||
|
getMemoryViewParams({ |
||||
|
include_docs: true, |
||||
|
}) |
||||
|
) |
||||
|
).rows.map(row => row.doc) |
||||
|
for (let viewDoc of views) { |
||||
|
response.push({ |
||||
|
name: viewDoc.name, |
||||
|
...viewDoc.view, |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
return response |
||||
|
} |
||||
|
|
||||
|
exports.saveView = async (db, originalName, viewName, viewTemplate) => { |
||||
|
if (env.SELF_HOSTED) { |
||||
|
const designDoc = await db.get("_design/database") |
||||
|
designDoc.views = { |
||||
|
...designDoc.views, |
||||
|
[viewName]: viewTemplate, |
||||
|
} |
||||
|
// view has been renamed
|
||||
|
if (originalName) { |
||||
|
delete designDoc.views[originalName] |
||||
|
} |
||||
|
await db.put(designDoc) |
||||
|
} else { |
||||
|
const id = generateMemoryViewID(viewName) |
||||
|
const originalId = originalName ? generateMemoryViewID(originalName) : null |
||||
|
const viewDoc = { |
||||
|
_id: id, |
||||
|
view: viewTemplate, |
||||
|
name: viewName, |
||||
|
tableId: viewTemplate.meta.tableId, |
||||
|
} |
||||
|
try { |
||||
|
const old = await db.get(id) |
||||
|
if (originalId) { |
||||
|
const originalDoc = await db.get(originalId) |
||||
|
await db.remove(originalDoc._id, originalDoc._rev) |
||||
|
} |
||||
|
if (old && old._rev) { |
||||
|
viewDoc._rev = old._rev |
||||
|
} |
||||
|
} catch (err) { |
||||
|
// didn't exist, just skip
|
||||
|
} |
||||
|
await db.put(viewDoc) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
exports.deleteView = async (db, viewName) => { |
||||
|
if (env.SELF_HOSTED) { |
||||
|
const designDoc = await db.get("_design/database") |
||||
|
const view = designDoc.views[viewName] |
||||
|
delete designDoc.views[viewName] |
||||
|
await db.put(designDoc) |
||||
|
return view |
||||
|
} else { |
||||
|
const id = generateMemoryViewID(viewName) |
||||
|
const viewDoc = await db.get(id) |
||||
|
await db.remove(viewDoc._id, viewDoc._rev) |
||||
|
return viewDoc.view |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
exports.migrateToInMemoryView = async (db, viewName) => { |
||||
|
// delete the view initially
|
||||
|
const designDoc = await db.get("_design/database") |
||||
|
const view = designDoc.views[viewName] |
||||
|
delete designDoc.views[viewName] |
||||
|
await db.put(designDoc) |
||||
|
await exports.saveView(db, null, viewName, view) |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
const PouchDB = require("pouchdb") |
||||
|
const memory = require("pouchdb-adapter-memory") |
||||
|
const newid = require("./newid") |
||||
|
|
||||
|
PouchDB.plugin(memory) |
||||
|
const Pouch = PouchDB.defaults({ |
||||
|
prefix: undefined, |
||||
|
adapter: "memory", |
||||
|
}) |
||||
|
|
||||
|
exports.runView = async (view, calculation, group, data) => { |
||||
|
// use a different ID each time for the DB, make sure they
|
||||
|
// are always unique for each query, don't want overlap
|
||||
|
// which could cause 409s
|
||||
|
const db = new Pouch(newid()) |
||||
|
// write all the docs to the in memory Pouch (remove revs)
|
||||
|
await db.bulkDocs( |
||||
|
data.map(row => ({ |
||||
|
...row, |
||||
|
_rev: undefined, |
||||
|
})) |
||||
|
) |
||||
|
let fn = (doc, emit) => emit(doc._id) |
||||
|
eval("fn = " + view.map.replace("function (doc)", "function (doc, emit)")) |
||||
|
const queryFns = { |
||||
|
meta: view.meta, |
||||
|
map: fn, |
||||
|
} |
||||
|
if (view.reduce) { |
||||
|
queryFns.reduce = view.reduce |
||||
|
} |
||||
|
const response = await db.query(queryFns, { |
||||
|
include_docs: !calculation, |
||||
|
group: !!group, |
||||
|
}) |
||||
|
// need to fix the revs to be totally accurate
|
||||
|
for (let row of response.rows) { |
||||
|
if (!row._rev || !row._id) { |
||||
|
continue |
||||
|
} |
||||
|
const found = data.find(possible => possible._id === row._id) |
||||
|
if (found) { |
||||
|
row._rev = found._rev |
||||
|
} |
||||
|
} |
||||
|
await db.destroy() |
||||
|
return response |
||||
|
} |
||||
Loading…
Reference in new issue