mirror of https://github.com/Budibase/budibase.git
38 changed files with 3611 additions and 3637 deletions
@ -0,0 +1,3 @@ |
|||||
|
[submodule "budibase-core"] |
||||
|
path = packages/core |
||||
|
url = git@github.com:Budibase/budibase-core.git |
||||
@ -0,0 +1,35 @@ |
|||||
|
[33mcommit 78a241d11c55ae717ba844c3d853e594d805e0a2[m[33m ([m[1;36mHEAD -> [m[1;32mmaster[m[33m)[m |
||||
|
Author: michael shanks <mike@budibase.com> |
||||
|
Date: Fri Jun 7 14:11:23 2019 +0100 |
||||
|
|
||||
|
mono-repo |
||||
|
|
||||
|
[33mcommit 04eef6ab4d291621114949c14097987ec1804274[m[33m ([m[1;31mbb/master[m[33m)[m |
||||
|
Author: michael shanks <mike@budibase.com> |
||||
|
Date: Fri Jun 7 12:22:23 2019 +0100 |
||||
|
|
||||
|
license AGPL |
||||
|
|
||||
|
[33mcommit 5bcf5157e0010aea34be4bc338057a75ae0befec[m |
||||
|
Author: michael shanks <mike@budibase.com> |
||||
|
Date: Fri Jun 7 12:09:06 2019 +0100 |
||||
|
|
||||
|
making OS friendly :) |
||||
|
|
||||
|
[33mcommit d5129fbda3c0fbb35e7275420aee0b2e8a4f6c2b[m |
||||
|
Author: michael shanks <mike@budibase.com> |
||||
|
Date: Fri Jun 7 12:02:48 2019 +0100 |
||||
|
|
||||
|
initialise master database working |
||||
|
|
||||
|
[33mcommit 36f9e7c64faf9c1ce27a1586337b4bd168fe88ec[m[33m ([m[1;31morigin/master[m[33m, [m[1;31morigin/HEAD[m[33m)[m |
||||
|
Author: Michael Shanks <mjashanks@hotmail.com> |
||||
|
Date: Fri Apr 5 16:30:29 2019 +0100 |
||||
|
|
||||
|
backup.. |
||||
|
|
||||
|
[33mcommit a8aa18d01d0640db6fb0f7bcb20e713b38b5610b[m |
||||
|
Author: Michael Shanks <mjashanks@hotmail.com> |
||||
|
Date: Tue Mar 19 21:45:21 2019 +0000 |
||||
|
|
||||
|
initial commit |
||||
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"packages": [ |
||||
|
"packages/*" |
||||
|
], |
||||
|
"version": "0.0.0" |
||||
|
} |
||||
@ -1,20 +1,7 @@ |
|||||
{ |
{ |
||||
"name": "budibase", |
"name": "root", |
||||
"version": "0.0.1", |
"private": true, |
||||
"description": "budibase wrapper repo for development", |
"devDependencies": { |
||||
"main": "index.js", |
"lerna": "^3.14.1" |
||||
"scripts": { |
|
||||
"test": "echo \"Error: no test specified\" && exit 1" |
|
||||
}, |
|
||||
"keywords": [ |
|
||||
"budibase" |
|
||||
], |
|
||||
"author": "Michael Shanks", |
|
||||
"license": "AGPL-3.0-or-later", |
|
||||
"dependencies": { |
|
||||
"argon2": "^0.23.0", |
|
||||
"budibase-core": "git+ssh://git@github.com:Budibase/budibase-core-dist.git", |
|
||||
"rimraf": "^2.6.3", |
|
||||
"yargs": "^13.2.4" |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,14 @@ |
|||||
|
{ |
||||
|
"name": "budibase-client-library", |
||||
|
"version": "0.0.1", |
||||
|
"description": "Client library for talking to budibase web server", |
||||
|
"main": "index.js", |
||||
|
"scripts": { |
||||
|
"test": "echo \"Error: no test specified\" && exit 1" |
||||
|
}, |
||||
|
"keywords": [ |
||||
|
"budibase" |
||||
|
], |
||||
|
"author": "Michael Shanks", |
||||
|
"license": "MPL-2.0" |
||||
|
} |
||||
@ -1,5 +1,5 @@ |
|||||
{ |
{ |
||||
"presets": ["@babel/env"], |
"presets": ["@babel/env"], |
||||
"sourceMaps": "inline", |
"sourceMaps": "inline", |
||||
"retainLines": true |
"retainLines": true |
||||
} |
} |
||||
@ -1,20 +1,20 @@ |
|||||
{ |
{ |
||||
// Use IntelliSense to learn about possible attributes. |
// Use IntelliSense to learn about possible attributes. |
||||
// Hover to view descriptions of existing attributes. |
// Hover to view descriptions of existing attributes. |
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |
||||
"version": "0.2.0", |
"version": "0.2.0", |
||||
"configurations": [ |
"configurations": [ |
||||
{ |
{ |
||||
"type": "node", |
"type": "node", |
||||
"request": "launch", |
"request": "launch", |
||||
"name": "debug memory", |
"name": "debug memory", |
||||
"program": "${workspaceFolder}/index.js", |
"program": "${workspaceFolder}/index.js", |
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node", |
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node", |
||||
"runtimeArgs": ["--nolazy"], |
"runtimeArgs": ["--nolazy"], |
||||
"args":["memory"], |
"args":["memory"], |
||||
"skipFiles": [ |
"skipFiles": [ |
||||
"<node_internals>/**/*.js" |
"<node_internals>/**/*.js" |
||||
] |
] |
||||
} |
} |
||||
] |
] |
||||
} |
} |
||||
@ -1,37 +1,37 @@ |
|||||
import fs from "fs"; |
import fs from "fs"; |
||||
import {join} from "path"; |
import {join} from "path"; |
||||
import {promisify} from 'es6-promisify'; |
import {promisify} from 'es6-promisify'; |
||||
import _rimraf from "rimraf"; |
import _rimraf from "rimraf"; |
||||
|
|
||||
const mkdir = promisify(fs.mkdir); |
const mkdir = promisify(fs.mkdir); |
||||
const rmdir = promisify(fs.rmdir); |
const rmdir = promisify(fs.rmdir); |
||||
const rimraf = promisify(_rimraf); |
const rimraf = promisify(_rimraf); |
||||
|
|
||||
const getConfig = async () => { |
const getConfig = async () => { |
||||
|
|
||||
const config = { |
const config = { |
||||
local: { |
local: { |
||||
root: "./output/local/files" |
root: "./output/local/files" |
||||
}, |
}, |
||||
memory: { |
memory: { |
||||
root:"./output/memory" |
root:"./output/memory" |
||||
}, |
}, |
||||
azure: { |
azure: { |
||||
root:"./output/azure" |
root:"./output/azure" |
||||
} |
} |
||||
}; |
}; |
||||
|
|
||||
await rimraf("./output"); |
await rimraf("./output"); |
||||
await mkdir("./output"); |
await mkdir("./output"); |
||||
|
|
||||
for(let type in config) { |
for(let type in config) { |
||||
await mkdir(join("output", type)); |
await mkdir(join("output", type)); |
||||
} |
} |
||||
|
|
||||
await mkdir("./output/local/files"); |
await mkdir("./output/local/files"); |
||||
|
|
||||
return config; |
return config; |
||||
}; |
}; |
||||
|
|
||||
|
|
||||
export default getConfig; |
export default getConfig; |
||||
@ -1,32 +1,32 @@ |
|||||
import fs from "fs"; |
import fs from "fs"; |
||||
import {mkdir} from "fs"; |
import {mkdir} from "fs"; |
||||
import {join} from "path"; |
import {join} from "path"; |
||||
import {promisify} from 'es6-promisify'; |
import {promisify} from 'es6-promisify'; |
||||
|
|
||||
mkdirp = promisify(mkdir); |
mkdirp = promisify(mkdir); |
||||
|
|
||||
|
|
||||
const getConfig = async () => { |
const getConfig = async () => { |
||||
|
|
||||
const config = { |
const config = { |
||||
local: { |
local: { |
||||
root: "./output/local/files" |
root: "./output/local/files" |
||||
}, |
}, |
||||
memory: {} |
memory: {} |
||||
}; |
}; |
||||
|
|
||||
try { |
try { |
||||
await mkdir("./output"); |
await mkdir("./output"); |
||||
} catch(e){} |
} catch(e){} |
||||
|
|
||||
for(let type in config) { |
for(let type in config) { |
||||
await mkdir(join("output", type)); |
await mkdir(join("output", type)); |
||||
} |
} |
||||
|
|
||||
await mkdir("./output/local/files"); |
await mkdir("./output/local/files"); |
||||
|
|
||||
return config; |
return config; |
||||
}; |
}; |
||||
|
|
||||
|
|
||||
export default getConfig; |
export default getConfig; |
||||
@ -1,86 +1,86 @@ |
|||||
import {SharedKeyCredential, BlockBlobURL, |
import {SharedKeyCredential, BlockBlobURL, |
||||
BlobURL, ContainerURL, ServiceURL, |
BlobURL, ContainerURL, ServiceURL, |
||||
StorageURL, Aborter} from "@azure/storage-blob"; |
StorageURL, Aborter} from "@azure/storage-blob"; |
||||
|
|
||||
export const createFile = ({containerUrl}) => async (key, content) => { |
export const createFile = ({containerUrl}) => async (key, content) => { |
||||
const blobURL = BlobURL.fromContainerURL(containerURL, key); |
const blobURL = BlobURL.fromContainerURL(containerURL, key); |
||||
const blockBlobURL = BlockBlobURL.fromBlobURL(blobURL); |
const blockBlobURL = BlockBlobURL.fromBlobURL(blobURL); |
||||
await blockBlobURL.upload( |
await blockBlobURL.upload( |
||||
Aborter.none, |
Aborter.none, |
||||
content, |
content, |
||||
content.length |
content.length |
||||
); |
); |
||||
}; |
}; |
||||
|
|
||||
export const updateFile = opts => async (path, content) => |
export const updateFile = opts => async (path, content) => |
||||
createFile(opts)(path,content); |
createFile(opts)(path,content); |
||||
|
|
||||
export const loadFile = ({containerUrl}) => async key => { |
export const loadFile = ({containerUrl}) => async key => { |
||||
const blobURL = BlobURL.fromContainerURL( |
const blobURL = BlobURL.fromContainerURL( |
||||
containerUrl, key); |
containerUrl, key); |
||||
|
|
||||
const downloadBlockBlobResponse = |
const downloadBlockBlobResponse = |
||||
await blobURL.download(Aborter.none, 0); |
await blobURL.download(Aborter.none, 0); |
||||
|
|
||||
return downloadBlockBlobResponse |
return downloadBlockBlobResponse |
||||
.readableStreamBody |
.readableStreamBody |
||||
.read(content.length) |
.read(content.length) |
||||
.toString(); |
.toString(); |
||||
}; |
}; |
||||
|
|
||||
export const exists = ({containerURL}) => async (key) => { |
export const exists = ({containerURL}) => async (key) => { |
||||
const blobURL = BlobURL.fromContainerURL(containerURL, key); |
const blobURL = BlobURL.fromContainerURL(containerURL, key); |
||||
const getPropsResponse = await blobURL.getProperties(); |
const getPropsResponse = await blobURL.getProperties(); |
||||
return getPropsResponse._response.StatusCode === 200; |
return getPropsResponse._response.StatusCode === 200; |
||||
} |
} |
||||
|
|
||||
export const deleteFile = ({containerURL}) => async key => { |
export const deleteFile = ({containerURL}) => async key => { |
||||
const blobURL = BlobURL.fromContainerURL( |
const blobURL = BlobURL.fromContainerURL( |
||||
containerURL, key); |
containerURL, key); |
||||
await blobURL.delete(Aborter.none); |
await blobURL.delete(Aborter.none); |
||||
} |
} |
||||
|
|
||||
export const createContainer = ({containerUrl}) => async () => |
export const createContainer = ({containerUrl}) => async () => |
||||
await containerUrl.create(Aborter.none); |
await containerUrl.create(Aborter.none); |
||||
|
|
||||
export const deleteContainer = ({containerUrl}) => async () => |
export const deleteContainer = ({containerUrl}) => async () => |
||||
await containerUrl.delete(Aborter.none); |
await containerUrl.delete(Aborter.none); |
||||
|
|
||||
const initialise = opts => { |
const initialise = opts => { |
||||
|
|
||||
const sharedKeyCredential = new SharedKeyCredential( |
const sharedKeyCredential = new SharedKeyCredential( |
||||
opts.account, |
opts.account, |
||||
opts.accountKey |
opts.accountKey |
||||
); |
); |
||||
|
|
||||
const pipeline = StorageURL.newPipeline(sharedKeyCredential); |
const pipeline = StorageURL.newPipeline(sharedKeyCredential); |
||||
|
|
||||
const serviceURL = new ServiceURL( |
const serviceURL = new ServiceURL( |
||||
`https://${account}.blob.core.windows.net`, |
`https://${account}.blob.core.windows.net`, |
||||
pipeline |
pipeline |
||||
); |
); |
||||
|
|
||||
const containerURL = ContainerURL.fromServiceURL( |
const containerURL = ContainerURL.fromServiceURL( |
||||
serviceURL, |
serviceURL, |
||||
opts.containerName |
opts.containerName |
||||
); |
); |
||||
|
|
||||
return ({ |
return ({ |
||||
containerURL |
containerURL |
||||
}); |
}); |
||||
|
|
||||
}; |
}; |
||||
|
|
||||
export default opts => { |
export default opts => { |
||||
const access = initialise(opts); |
const access = initialise(opts); |
||||
return ({ |
return ({ |
||||
createFile : createFile(access), |
createFile : createFile(access), |
||||
updateFile : updateFile(access), |
updateFile : updateFile(access), |
||||
loadFile : loadFile(access), |
loadFile : loadFile(access), |
||||
exists : exists(access), |
exists : exists(access), |
||||
|
|
||||
datastoreType : "azure-blob-storage", |
datastoreType : "azure-blob-storage", |
||||
datastoreDescription: "", |
datastoreDescription: "", |
||||
data |
data |
||||
}); |
}); |
||||
}; |
}; |
||||
@ -1,126 +1,126 @@ |
|||||
const {promisify} = require('util'); |
const {promisify} = require('util'); |
||||
const fs = require("fs"); |
const fs = require("fs"); |
||||
const {join} = require("path"); |
const {join} = require("path"); |
||||
|
|
||||
const readFile = promisify(fs.readFile); |
const readFile = promisify(fs.readFile); |
||||
const writeFile = (path, content) => |
const writeFile = (path, content) => |
||||
promisify(fs.writeFile)(path, content, "utf8"); |
promisify(fs.writeFile)(path, content, "utf8"); |
||||
const access = promisify(fs.access); |
const access = promisify(fs.access); |
||||
const mkdir = promisify(fs.mkdir); |
const mkdir = promisify(fs.mkdir); |
||||
const rmdir = promisify(fs.rmdir); |
const rmdir = promisify(fs.rmdir); |
||||
const unlink = promisify(fs.unlink); |
const unlink = promisify(fs.unlink); |
||||
const readdir = promisify(fs.readdir); |
const readdir = promisify(fs.readdir); |
||||
const rename = promisify(fs.rename); |
const rename = promisify(fs.rename); |
||||
|
|
||||
const updateFile = root => async (path, file) => |
const updateFile = root => async (path, file) => |
||||
await writeFile( |
await writeFile( |
||||
join(root,path), |
join(root,path), |
||||
file |
file |
||||
); |
); |
||||
|
|
||||
const createFile = updateFile; |
const createFile = updateFile; |
||||
|
|
||||
const loadFile = root => async (path) => |
const loadFile = root => async (path) => |
||||
await readFile( |
await readFile( |
||||
join(root,path) |
join(root,path) |
||||
, "utf8"); |
, "utf8"); |
||||
|
|
||||
const exists = root => async (path) => { |
const exists = root => async (path) => { |
||||
try { |
try { |
||||
await access( |
await access( |
||||
join(root,path) |
join(root,path) |
||||
); |
); |
||||
} catch (e) { |
} catch (e) { |
||||
return false; |
return false; |
||||
} |
} |
||||
return true; |
return true; |
||||
}; |
}; |
||||
|
|
||||
const createFolder = root => async (path) => |
const createFolder = root => async (path) => |
||||
await mkdir( |
await mkdir( |
||||
join(root, path)); |
join(root, path)); |
||||
|
|
||||
const deleteFile = root => async (path) => |
const deleteFile = root => async (path) => |
||||
await unlink( |
await unlink( |
||||
join(root, path) |
join(root, path) |
||||
); |
); |
||||
|
|
||||
module.exports.deleteFile = deleteFile; |
module.exports.deleteFile = deleteFile; |
||||
|
|
||||
const deleteFolder = root => async (path) => |
const deleteFolder = root => async (path) => |
||||
await rmdir( |
await rmdir( |
||||
join(root, path)); |
join(root, path)); |
||||
|
|
||||
const readableFileStream = root => async path => |
const readableFileStream = root => async path => |
||||
fs.createReadStream( |
fs.createReadStream( |
||||
join(root, path), "utf8" |
join(root, path), "utf8" |
||||
); |
); |
||||
|
|
||||
const writableFileStream = root => async path => |
const writableFileStream = root => async path => |
||||
fs.createWriteStream( |
fs.createWriteStream( |
||||
join(root, path), "utf8" |
join(root, path), "utf8" |
||||
); |
); |
||||
|
|
||||
const getFolderContents = root => async path => { |
const getFolderContents = root => async path => { |
||||
await readdir( |
await readdir( |
||||
join(root, path) |
join(root, path) |
||||
); |
); |
||||
}; |
}; |
||||
|
|
||||
const renameFile = root => async (oldPath, newPath) => |
const renameFile = root => async (oldPath, newPath) => |
||||
await rename( |
await rename( |
||||
join(root, oldPath), |
join(root, oldPath), |
||||
join(root, newPath) |
join(root, newPath) |
||||
); |
); |
||||
|
|
||||
const datastoreFolder = (applicationId, instanceId) => |
const datastoreFolder = (applicationId, instanceId) => |
||||
applicationId === "master" ? "master" |
applicationId === "master" ? "master" |
||||
: `app.${applicationId}.${instanceId}`; |
: `app.${applicationId}.${instanceId}`; |
||||
|
|
||||
const createEmptyDb = (rootConfig) => async (applicationId, instanceId) => { |
const createEmptyDb = (rootConfig) => async (applicationId, instanceId) => { |
||||
const folder = datastoreFolder(applicationId, instanceId); |
const folder = datastoreFolder(applicationId, instanceId); |
||||
const dbRootConfig = getDbRootConfig(rootConfig, applicationId, instanceId); |
const dbRootConfig = getDbRootConfig(rootConfig, applicationId, instanceId); |
||||
await createFolder(dbRootConfig)(folder); |
await createFolder(dbRootConfig)(folder); |
||||
return folder; |
return folder; |
||||
}; |
}; |
||||
|
|
||||
const getDatastoreConfig = (rootConfig) => (applicationId, instanceId) => |
const getDatastoreConfig = (rootConfig) => (applicationId, instanceId) => |
||||
join(rootConfig.rootPath, |
join(rootConfig.rootPath, |
||||
datastoreFolder( |
datastoreFolder( |
||||
applicationId, instanceId |
applicationId, instanceId |
||||
)); |
)); |
||||
|
|
||||
const getMasterDbRootConfig = (rootConfig) => () => rootConfig.rootPath; |
const getMasterDbRootConfig = (rootConfig) => () => rootConfig.rootPath; |
||||
const getInstanceDbRootConfig = (rootConfig) => async (applicationId, instanceId) => rootConfig.rootPath; |
const getInstanceDbRootConfig = (rootConfig) => async (applicationId, instanceId) => rootConfig.rootPath; |
||||
const getDbRootConfig = (rootConfig, applicationId, instanceId) => |
const getDbRootConfig = (rootConfig, applicationId, instanceId) => |
||||
applicationId === "master" |
applicationId === "master" |
||||
? getMasterDbRootConfig(rootConfig)() |
? getMasterDbRootConfig(rootConfig)() |
||||
: getInstanceDbRootConfig(rootConfig)(applicationId, instanceId); |
: getInstanceDbRootConfig(rootConfig)(applicationId, instanceId); |
||||
|
|
||||
module.exports.databaseManager = rootConfig => ({ |
module.exports.databaseManager = rootConfig => ({ |
||||
createEmptyDb:createEmptyDb(rootConfig), |
createEmptyDb:createEmptyDb(rootConfig), |
||||
getDatastoreConfig:getDatastoreConfig(rootConfig), |
getDatastoreConfig:getDatastoreConfig(rootConfig), |
||||
getMasterDbRootConfig:getMasterDbRootConfig(rootConfig), |
getMasterDbRootConfig:getMasterDbRootConfig(rootConfig), |
||||
getInstanceDbRootConfig:getInstanceDbRootConfig(rootConfig) |
getInstanceDbRootConfig:getInstanceDbRootConfig(rootConfig) |
||||
}); |
}); |
||||
|
|
||||
module.exports.getDatastore = rootFolderPath => ({ |
module.exports.getDatastore = rootFolderPath => ({ |
||||
createFile : createFile(rootFolderPath), |
createFile : createFile(rootFolderPath), |
||||
updateFile : updateFile(rootFolderPath), |
updateFile : updateFile(rootFolderPath), |
||||
loadFile : loadFile(rootFolderPath), |
loadFile : loadFile(rootFolderPath), |
||||
exists : exists(rootFolderPath), |
exists : exists(rootFolderPath), |
||||
deleteFile : deleteFile(rootFolderPath), |
deleteFile : deleteFile(rootFolderPath), |
||||
createFolder: createFolder(rootFolderPath), |
createFolder: createFolder(rootFolderPath), |
||||
deleteFolder: deleteFolder(rootFolderPath), |
deleteFolder: deleteFolder(rootFolderPath), |
||||
readableFileStream: readableFileStream(rootFolderPath), |
readableFileStream: readableFileStream(rootFolderPath), |
||||
writableFileStream: writableFileStream(rootFolderPath), |
writableFileStream: writableFileStream(rootFolderPath), |
||||
renameFile: renameFile(rootFolderPath), |
renameFile: renameFile(rootFolderPath), |
||||
getFolderContents: getFolderContents(rootFolderPath), |
getFolderContents: getFolderContents(rootFolderPath), |
||||
createEmptyDb: createEmptyDb(rootFolderPath), |
createEmptyDb: createEmptyDb(rootFolderPath), |
||||
datastoreType : "local", |
datastoreType : "local", |
||||
datastoreDescription: rootFolderPath |
datastoreDescription: rootFolderPath |
||||
}); |
}); |
||||
|
|
||||
module.exports.configParameters = { |
module.exports.configParameters = { |
||||
rootPath: "Root Data Folder" |
rootPath: "Root Data Folder" |
||||
}; |
}; |
||||
@ -1,128 +1,128 @@ |
|||||
import {isUndefined, has} from "lodash"; |
import {isUndefined, has} from "lodash"; |
||||
import {take} from "lodash/fp"; |
import {take} from "lodash/fp"; |
||||
import {Readable, Writable} from "readable-stream"; |
import {Readable, Writable} from "readable-stream"; |
||||
import { Buffer } from "safe-buffer"; |
import { Buffer } from "safe-buffer"; |
||||
import {splitKey, joinKey, $} from "../src/common"; |
import {splitKey, joinKey, $} from "../src/common"; |
||||
import {getLastPartInKey} from "../src/templateApi/heirarchy"; |
import {getLastPartInKey} from "../src/templateApi/heirarchy"; |
||||
|
|
||||
const folderMarker = "OH-YES-ITSA-FOLDER-"; |
const folderMarker = "OH-YES-ITSA-FOLDER-"; |
||||
const isFolder = val => val.includes(folderMarker); |
const isFolder = val => val.includes(folderMarker); |
||||
|
|
||||
const getParentFolderKey = key => |
const getParentFolderKey = key => |
||||
$(key, [ |
$(key, [ |
||||
splitKey, |
splitKey, |
||||
take((splitKey(key).length - 1)), |
take((splitKey(key).length - 1)), |
||||
joinKey, |
joinKey, |
||||
]); |
]); |
||||
|
|
||||
const getParentFolder = (data,key) => { |
const getParentFolder = (data,key) => { |
||||
const parentKey = getParentFolderKey(key); |
const parentKey = getParentFolderKey(key); |
||||
if(data[parentKey] === undefined) |
if(data[parentKey] === undefined) |
||||
throw new Error("Parent folder for " + key + " does not exist (" + parentKey + ")"); |
throw new Error("Parent folder for " + key + " does not exist (" + parentKey + ")"); |
||||
return JSON.parse(data[parentKey]); |
return JSON.parse(data[parentKey]); |
||||
} |
} |
||||
|
|
||||
const addItemToParentFolder = (data, path) => { |
const addItemToParentFolder = (data, path) => { |
||||
if(getParentFolderKey(path) === "/") return; |
if(getParentFolderKey(path) === "/") return; |
||||
const parentFolder = getParentFolder(data, path); |
const parentFolder = getParentFolder(data, path); |
||||
parentFolder.items.push( |
parentFolder.items.push( |
||||
getLastPartInKey(path)); |
getLastPartInKey(path)); |
||||
data[getParentFolderKey(path)] = JSON.stringify(parentFolder); |
data[getParentFolderKey(path)] = JSON.stringify(parentFolder); |
||||
} |
} |
||||
|
|
||||
export const createFile = data => async (path, content) => { |
export const createFile = data => async (path, content) => { |
||||
if(await exists(data)(path)) { |
if(await exists(data)(path)) { |
||||
throw new Error(path + " already exists"); |
throw new Error(path + " already exists"); |
||||
} |
} |
||||
addItemToParentFolder(data, path); |
addItemToParentFolder(data, path); |
||||
data[path] = content; |
data[path] = content; |
||||
}; |
}; |
||||
export const updateFile = data => async (path, content) => { |
export const updateFile = data => async (path, content) => { |
||||
// putting this check in to force use of create
|
// putting this check in to force use of create
|
||||
if(!await exists(data)(path)) throw new Error("cannot update " + path + " - does not exist"); |
if(!await exists(data)(path)) throw new Error("cannot update " + path + " - does not exist"); |
||||
data[path] = content; |
data[path] = content; |
||||
} |
} |
||||
|
|
||||
export const writableFileStream = data => async (path) => { |
export const writableFileStream = data => async (path) => { |
||||
//if(!await exists(data)(path)) throw new Error("cannot write stream to " + path + " - does not exist");
|
//if(!await exists(data)(path)) throw new Error("cannot write stream to " + path + " - does not exist");
|
||||
const stream = Writable(); |
const stream = Writable(); |
||||
stream._write = (chunk, encoding, done) => { |
stream._write = (chunk, encoding, done) => { |
||||
data[path] = data[path] === undefined |
data[path] = data[path] === undefined |
||||
? [] : data[path]; |
? [] : data[path]; |
||||
data[path] = [...data[path], ...chunk]; |
data[path] = [...data[path], ...chunk]; |
||||
done(); |
done(); |
||||
}; |
}; |
||||
return stream; |
return stream; |
||||
}; |
}; |
||||
|
|
||||
export const readableFileStream = data => async (path) => { |
export const readableFileStream = data => async (path) => { |
||||
if(!await exists(data)(path)) |
if(!await exists(data)(path)) |
||||
throw new Error("cannot read stream from " + path + " - does not exist"); |
throw new Error("cannot read stream from " + path + " - does not exist"); |
||||
const s = new Readable(); |
const s = new Readable(); |
||||
s._read = () => { |
s._read = () => { |
||||
s.push(Buffer.from(data[path])); |
s.push(Buffer.from(data[path])); |
||||
s.push(null); |
s.push(null); |
||||
}; |
}; |
||||
return s; |
return s; |
||||
}; |
}; |
||||
|
|
||||
export const renameFile = data => async (oldKey, newKey) => { |
export const renameFile = data => async (oldKey, newKey) => { |
||||
if(!await exists(data)(oldKey)) throw new Error("cannot rename path: " + oldKey + " ... does not exist"); |
if(!await exists(data)(oldKey)) throw new Error("cannot rename path: " + oldKey + " ... does not exist"); |
||||
if(await exists(data)(newKey)) throw new Error("cannot rename path: " + newKey + " ... already exists"); |
if(await exists(data)(newKey)) throw new Error("cannot rename path: " + newKey + " ... already exists"); |
||||
data[newKey] = data[oldKey]; |
data[newKey] = data[oldKey]; |
||||
delete data[oldKey]; |
delete data[oldKey]; |
||||
}; |
}; |
||||
|
|
||||
export const loadFile = data => async (path) => { |
export const loadFile = data => async (path) => { |
||||
const result = data[path]; |
const result = data[path]; |
||||
if(isUndefined(result)) throw new Error("Load failed - path " + path + " does not exist"); |
if(isUndefined(result)) throw new Error("Load failed - path " + path + " does not exist"); |
||||
return result; |
return result; |
||||
}; |
}; |
||||
export const exists = data => async (path) => has(data, path); |
export const exists = data => async (path) => has(data, path); |
||||
export const deleteFile = data => async (path) => { |
export const deleteFile = data => async (path) => { |
||||
if(!await exists(data)(path)) |
if(!await exists(data)(path)) |
||||
throw new Error("Cannot delete file, path " + path + " does not exist"); |
throw new Error("Cannot delete file, path " + path + " does not exist"); |
||||
if(isFolder(data[path])) throw new Error("DeleteFile: Path " + path + " is a folder, not a file"); |
if(isFolder(data[path])) throw new Error("DeleteFile: Path " + path + " is a folder, not a file"); |
||||
const parentFolder = getParentFolder(data, path); |
const parentFolder = getParentFolder(data, path); |
||||
parentFolder.items = parentFolder.items.filter(i => i !== getLastPartInKey(path)); |
parentFolder.items = parentFolder.items.filter(i => i !== getLastPartInKey(path)); |
||||
data[getParentFolderKey(path)] = JSON.stringify(parentFolder); |
data[getParentFolderKey(path)] = JSON.stringify(parentFolder); |
||||
delete data[path]; |
delete data[path]; |
||||
} |
} |
||||
export const createFolder = data => async (path) => { |
export const createFolder = data => async (path) => { |
||||
if(await exists(data)(path)) throw new Error("Cannot create folder, path " + path + " already exists"); |
if(await exists(data)(path)) throw new Error("Cannot create folder, path " + path + " already exists"); |
||||
addItemToParentFolder(data, path); |
addItemToParentFolder(data, path); |
||||
data[path] = JSON.stringify({folderMarker, items:[]}); |
data[path] = JSON.stringify({folderMarker, items:[]}); |
||||
} |
} |
||||
export const deleteFolder = data => async (path) => { |
export const deleteFolder = data => async (path) => { |
||||
if(!await exists(data)(path)) throw new Error("Cannot delete folder, path " + path + " does not exist"); |
if(!await exists(data)(path)) throw new Error("Cannot delete folder, path " + path + " does not exist"); |
||||
if(!isFolder(data[path])) |
if(!isFolder(data[path])) |
||||
throw new Error("DeleteFolder: Path " + path + " is not a folder"); |
throw new Error("DeleteFolder: Path " + path + " is not a folder"); |
||||
delete data[path]; |
delete data[path]; |
||||
} |
} |
||||
|
|
||||
export const getFolderContents = data => async (folderPath) => { |
export const getFolderContents = data => async (folderPath) => { |
||||
if(!isFolder(data[folderPath])) |
if(!isFolder(data[folderPath])) |
||||
throw new Error("Not a folder: " + folderPath); |
throw new Error("Not a folder: " + folderPath); |
||||
if(!await exists(data)(folderPath)) |
if(!await exists(data)(folderPath)) |
||||
throw new Error("Folder does not exist: " + folderPath); |
throw new Error("Folder does not exist: " + folderPath); |
||||
return JSON.parse(data[folderPath]).items; |
return JSON.parse(data[folderPath]).items; |
||||
}; |
}; |
||||
|
|
||||
export default data => { |
export default data => { |
||||
return { |
return { |
||||
createFile : createFile(data), |
createFile : createFile(data), |
||||
updateFile : updateFile(data), |
updateFile : updateFile(data), |
||||
loadFile : loadFile(data), |
loadFile : loadFile(data), |
||||
exists : exists(data), |
exists : exists(data), |
||||
deleteFile : deleteFile(data), |
deleteFile : deleteFile(data), |
||||
createFolder: createFolder(data), |
createFolder: createFolder(data), |
||||
deleteFolder: deleteFolder(data), |
deleteFolder: deleteFolder(data), |
||||
readableFileStream: readableFileStream(data), |
readableFileStream: readableFileStream(data), |
||||
writableFileStream: writableFileStream(data), |
writableFileStream: writableFileStream(data), |
||||
renameFile: renameFile(data), |
renameFile: renameFile(data), |
||||
getFolderContents: getFolderContents(data), |
getFolderContents: getFolderContents(data), |
||||
datastoreType : "memory", |
datastoreType : "memory", |
||||
datastoreDescription: "", |
datastoreDescription: "", |
||||
data |
data |
||||
}; |
}; |
||||
}; |
}; |
||||
@ -1,29 +1,29 @@ |
|||||
import local from "./datastores/local"; |
import local from "./datastores/local"; |
||||
import azureBlob from "./datastores/azure-blob"; |
import azureBlob from "./datastores/azure-blob"; |
||||
import memory from "./datastores/memory"; |
import memory from "./datastores/memory"; |
||||
import getConfig from "./config"; |
import getConfig from "./config"; |
||||
import tests from "./tests"; |
import tests from "./tests"; |
||||
|
|
||||
const initialise = async () => { |
const initialise = async () => { |
||||
|
|
||||
const type = process.argv[2]; |
const type = process.argv[2]; |
||||
const config = (await getConfig())[type]; |
const config = (await getConfig())[type]; |
||||
|
|
||||
switch (type) { |
switch (type) { |
||||
case "local": |
case "local": |
||||
return {datastore:local(config.root), config}; |
return {datastore:local(config.root), config}; |
||||
case "memory": |
case "memory": |
||||
return {datastore:memory(config), config}; |
return {datastore:memory(config), config}; |
||||
case "azure": |
case "azure": |
||||
return {datastore:azureBlob(config), config}; |
return {datastore:azureBlob(config), config}; |
||||
default: |
default: |
||||
break; |
break; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
initialise() |
initialise() |
||||
.then(init => { |
.then(init => { |
||||
return tests(init.datastore, init.config); |
return tests(init.datastore, init.config); |
||||
}) |
}) |
||||
.then(_ => console.log("done")) |
.then(_ => console.log("done")) |
||||
.catch(e => console.log(e)); |
.catch(e => console.log(e)); |
||||
@ -1,39 +1,39 @@ |
|||||
import {eventsList} from "budibase-core"; |
import {eventsList} from "budibase-core"; |
||||
import {filter,union,has,map} from "lodash/fp"; |
import {filter,union,has,map} from "lodash/fp"; |
||||
import records from "./records"; |
import records from "./records"; |
||||
|
|
||||
const allEventsOfType = type => |
const allEventsOfType = type => |
||||
filter( |
filter( |
||||
e => e.endsWith(`:${type}`) |
e => e.endsWith(`:${type}`) |
||||
)(eventsList); |
)(eventsList); |
||||
|
|
||||
const getEventNamespace = ev => { |
const getEventNamespace = ev => { |
||||
const parts = ev.split(":"); |
const parts = ev.split(":"); |
||||
return `${parts[0]}:${parts[1]}`; |
return `${parts[0]}:${parts[1]}`; |
||||
} |
} |
||||
|
|
||||
const hasRecord = has("record"); |
const hasRecord = has("record"); |
||||
|
|
||||
export const register = (app, logTimeElapsed, eventNamespaces = []) => { |
export const register = (app, logTimeElapsed, eventNamespaces = []) => { |
||||
const onCompleteEvents = |
const onCompleteEvents = |
||||
eventNamespaces.length === 0 |
eventNamespaces.length === 0 |
||||
? allEventsOfType("onComplete") |
? allEventsOfType("onComplete") |
||||
: map(e => `${e}:onComplete`)(eventNamespaces) |
: map(e => `${e}:onComplete`)(eventNamespaces) |
||||
|
|
||||
const onErrorEvents = |
const onErrorEvents = |
||||
eventNamespaces.length === 0 |
eventNamespaces.length === 0 |
||||
? allEventsOfType("onError") |
? allEventsOfType("onError") |
||||
: map(e => `${e}:onError`)(eventNamespaces) |
: map(e => `${e}:onError`)(eventNamespaces) |
||||
|
|
||||
for(let ev of union(onCompleteEvents)(onErrorEvents)) { |
for(let ev of union(onCompleteEvents)(onErrorEvents)) { |
||||
app.subscribe(ev, (_, ctx) => { |
app.subscribe(ev, (_, ctx) => { |
||||
const info = |
const info = |
||||
hasRecord(ctx) |
hasRecord(ctx) |
||||
? ctx.record.type() |
? ctx.record.type() |
||||
: ""; |
: ""; |
||||
|
|
||||
logTimeElapsed( |
logTimeElapsed( |
||||
ev, ctx.elapsed, info); |
ev, ctx.elapsed, info); |
||||
}); |
}); |
||||
} |
} |
||||
}; |
}; |
||||
@ -1,9 +1,9 @@ |
|||||
import {map} from "lodash"; |
import {map} from "lodash"; |
||||
|
|
||||
export const action = (name, run, iterator=iterateActionTimes(1)) => ({name, run, iterator}); |
export const action = (name, run, iterator=iterateActionTimes(1)) => ({name, run, iterator}); |
||||
|
|
||||
export const iterateActionTimes = times => run => |
export const iterateActionTimes = times => run => |
||||
map([...Array(times).keys()], run); |
map([...Array(times).keys()], run); |
||||
|
|
||||
export const iterateCollection = getCollection => run => |
export const iterateCollection = getCollection => run => |
||||
map(getCollection(), run); |
map(getCollection(), run); |
||||
@ -1,57 +1,57 @@ |
|||||
import setup from "./setup"; |
import setup from "./setup"; |
||||
import records from "./records"; |
import records from "./records"; |
||||
import {register} from "./diagnosticPlugin"; |
import {register} from "./diagnosticPlugin"; |
||||
import pLimit from "p-limit"; |
import pLimit from "p-limit"; |
||||
import papa from "papaparse"; |
import papa from "papaparse"; |
||||
import {writeFileSync} from "fs"; |
import {writeFileSync} from "fs"; |
||||
|
|
||||
const limit = pLimit(1); |
const limit = pLimit(1); |
||||
|
|
||||
const iterateActions = async (apis,getIterator) => { |
const iterateActions = async (apis,getIterator) => { |
||||
const iterator = getIterator(apis); |
const iterator = getIterator(apis); |
||||
let result = iterator(); |
let result = iterator(); |
||||
while(!result.done) { |
while(!result.done) { |
||||
try { |
try { |
||||
const runPromises = result.action.iterator(i => |
const runPromises = result.action.iterator(i => |
||||
limit(() => result.action.run(i)) |
limit(() => result.action.run(i)) |
||||
); |
); |
||||
|
|
||||
let n = 1; |
let n = 1; |
||||
await Promise.all(runPromises); |
await Promise.all(runPromises); |
||||
result = iterator(); |
result = iterator(); |
||||
} catch(e) { |
} catch(e) { |
||||
e.message = `FAILED: ${result.action.name}: ${e.message}`; |
e.message = `FAILED: ${result.action.name}: ${e.message}`; |
||||
throw e; |
throw e; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
export default async (datastore,config) => { |
export default async (datastore,config) => { |
||||
|
|
||||
const apis = await setup(datastore); |
const apis = await setup(datastore); |
||||
|
|
||||
const diagnostics = []; |
const diagnostics = []; |
||||
let currentRecordCount = 0; |
let currentRecordCount = 0; |
||||
|
|
||||
register(apis, (ev, elapsed, info) => { |
register(apis, (ev, elapsed, info) => { |
||||
if(ev === "recordApi:save:onComplete") { |
if(ev === "recordApi:save:onComplete") { |
||||
currentRecordCount++; |
currentRecordCount++; |
||||
} else if(ev === "recordApi:delete:onComplete") { |
} else if(ev === "recordApi:delete:onComplete") { |
||||
currentRecordCount--; |
currentRecordCount--; |
||||
} |
} |
||||
diagnostics.push( |
diagnostics.push( |
||||
{method:ev, elapsed, info, count:currentRecordCount} |
{method:ev, elapsed, info, count:currentRecordCount} |
||||
); |
); |
||||
console.log(`${ev} ${info} ${elapsed/1000} s`); |
console.log(`${ev} ${info} ${elapsed/1000} s`); |
||||
}, [ |
}, [ |
||||
"recordApi:save", |
"recordApi:save", |
||||
"recordApi:load", |
"recordApi:load", |
||||
"viewApi:listItems", |
"viewApi:listItems", |
||||
"recordApi:delete"]); |
"recordApi:delete"]); |
||||
|
|
||||
await iterateActions(apis, records); |
await iterateActions(apis, records); |
||||
|
|
||||
const diagnosticscsv = papa.unparse(diagnostics); |
const diagnosticscsv = papa.unparse(diagnostics); |
||||
|
|
||||
writeFileSync(config.root + "\\results.csv", diagnosticscsv, {encoding:"utf8"}); |
writeFileSync(config.root + "\\results.csv", diagnosticscsv, {encoding:"utf8"}); |
||||
}; |
}; |
||||
@ -1,96 +1,96 @@ |
|||||
import {action, iterateActionTimes, iterateCollection} from "./helpers"; |
import {action, iterateActionTimes, iterateCollection} from "./helpers"; |
||||
import {isUndefined, union, takeRight} from "lodash"; |
import {isUndefined, union, takeRight} from "lodash"; |
||||
|
|
||||
const createClient = (apis, getState) => async (i) => { |
const createClient = (apis, getState) => async (i) => { |
||||
const client = apis.recordApi.getNew("/clients", "client"); |
const client = apis.recordApi.getNew("/clients", "client"); |
||||
client.FamilyName = "Humperdink"; |
client.FamilyName = "Humperdink"; |
||||
client.Address1 = `${i} Mainitucetts Avenue`; |
client.Address1 = `${i} Mainitucetts Avenue`; |
||||
client.Address2 = "Longerton Road South"; |
client.Address2 = "Longerton Road South"; |
||||
client.Address3 = "Chalico City"; |
client.Address3 = "Chalico City"; |
||||
client.Address4 = "Northern Humranistan"; |
client.Address4 = "Northern Humranistan"; |
||||
client.Postcode = "BY71 5FR"; |
client.Postcode = "BY71 5FR"; |
||||
client.CreatedDate = new Date(); |
client.CreatedDate = new Date(); |
||||
|
|
||||
const state = getState(); |
const state = getState(); |
||||
if(isUndefined(state.clientKeys)) state.clientKeys = []; |
if(isUndefined(state.clientKeys)) state.clientKeys = []; |
||||
state.clientKeys.push(client.key()); |
state.clientKeys.push(client.key()); |
||||
|
|
||||
await apis.recordApi.save(client); |
await apis.recordApi.save(client); |
||||
|
|
||||
return client.key(); |
return client.key(); |
||||
} |
} |
||||
|
|
||||
const getClient = (apis, getState) => async (k) => { |
const getClient = (apis, getState) => async (k) => { |
||||
const state = getState(); |
const state = getState(); |
||||
if(isUndefined(state.clients)) state.clients = []; |
if(isUndefined(state.clients)) state.clients = []; |
||||
|
|
||||
const client = await apis.recordApi.load(k); |
const client = await apis.recordApi.load(k); |
||||
state.clients.push(client); |
state.clients.push(client); |
||||
|
|
||||
return `key: ${k} , add1: ${client.Address1} , count: ${state.clients.length}`; |
return `key: ${k} , add1: ${client.Address1} , count: ${state.clients.length}`; |
||||
} |
} |
||||
|
|
||||
const listClients = (apis, getState) => async () => { |
const listClients = (apis, getState) => async () => { |
||||
const clients = await apis.viewApi.listItems("/clients/default"); |
const clients = await apis.viewApi.listItems("/clients/default"); |
||||
const state = getState(); |
const state = getState(); |
||||
if(state.clientKeys.length !== clients.length) { |
if(state.clientKeys.length !== clients.length) { |
||||
throw new Error( |
throw new Error( |
||||
"list CLients, expected " |
"list CLients, expected " |
||||
+ state.clientKeys.length.toString() |
+ state.clientKeys.length.toString() |
||||
+ " clients, actual " |
+ " clients, actual " |
||||
+ clients.length.toString() |
+ clients.length.toString() |
||||
) |
) |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
const deleteClient = (apis, getState) => async k => { |
const deleteClient = (apis, getState) => async k => { |
||||
await apis.recordApi.delete(k); |
await apis.recordApi.delete(k); |
||||
const state = getState(); |
const state = getState(); |
||||
state.clientKeys = state.clientKeys.filter(key => key !== k); |
state.clientKeys = state.clientKeys.filter(key => key !== k); |
||||
} |
} |
||||
|
|
||||
|
|
||||
export default (apis) => { |
export default (apis) => { |
||||
|
|
||||
const state = {}; |
const state = {}; |
||||
const getState = () => state; |
const getState = () => state; |
||||
|
|
||||
const noOfRecords = 10000; |
const noOfRecords = 10000; |
||||
const recordsPerIteration = 10; |
const recordsPerIteration = 10; |
||||
const noOfIterations = noOfRecords / recordsPerIteration; |
const noOfIterations = noOfRecords / recordsPerIteration; |
||||
|
|
||||
const actionsInOneIteration = () => ([ |
const actionsInOneIteration = () => ([ |
||||
|
|
||||
action("Create client", createClient(apis, getState), |
action("Create client", createClient(apis, getState), |
||||
iterateActionTimes(recordsPerIteration)), |
iterateActionTimes(recordsPerIteration)), |
||||
|
|
||||
/*action("Get client", getClient(apis, getState), |
/*action("Get client", getClient(apis, getState), |
||||
iterateCollection(() => takeRight(getState().clientKeys, recordsPerIteration))),*/ |
iterateCollection(() => takeRight(getState().clientKeys, recordsPerIteration))),*/ |
||||
|
|
||||
action("List Clients", listClients(apis, getState)) |
action("List Clients", listClients(apis, getState)) |
||||
]); |
]); |
||||
|
|
||||
let actions = []; |
let actions = []; |
||||
for (let index = 0; index < noOfIterations; index++) { |
for (let index = 0; index < noOfIterations; index++) { |
||||
actions = union(actions, actionsInOneIteration()); |
actions = union(actions, actionsInOneIteration()); |
||||
} |
} |
||||
|
|
||||
/* |
/* |
||||
for (let index = 0; index < noOfIterations; index++) { |
for (let index = 0; index < noOfIterations; index++) { |
||||
actions.push( |
actions.push( |
||||
action("Delete Clients", deleteClient(apis, getState), |
action("Delete Clients", deleteClient(apis, getState), |
||||
iterateCollection(() => takeRight(getState().clientKeys, recordsPerIteration))), |
iterateCollection(() => takeRight(getState().clientKeys, recordsPerIteration))), |
||||
action("List Clients", listClients(apis, getState)) |
action("List Clients", listClients(apis, getState)) |
||||
); |
); |
||||
}*/ |
}*/ |
||||
let actionIndex = 0; |
let actionIndex = 0; |
||||
|
|
||||
return () => { |
return () => { |
||||
if(actionIndex == actions.length) { |
if(actionIndex == actions.length) { |
||||
return {done:true}; |
return {done:true}; |
||||
} |
} |
||||
const result = {action:actions[actionIndex], done:false}; |
const result = {action:actions[actionIndex], done:false}; |
||||
actionIndex++; |
actionIndex++; |
||||
return result; |
return result; |
||||
}; |
}; |
||||
}; |
}; |
||||
@ -1,70 +1,70 @@ |
|||||
import {getAppApis, getTemplateApi, setupDatastore} from "budibase-core"; |
import {getAppApis, getTemplateApi, setupDatastore} from "budibase-core"; |
||||
import {action} from "./helpers"; |
import {action} from "./helpers"; |
||||
|
|
||||
const addField = templateApi => type => (record, name) => { |
const addField = templateApi => type => (record, name) => { |
||||
const field = templateApi.getNewField(type); |
const field = templateApi.getNewField(type); |
||||
field.name = name; |
field.name = name; |
||||
field.type = type; |
field.type = type; |
||||
field.label = name; |
field.label = name; |
||||
templateApi.addField( |
templateApi.addField( |
||||
record, |
record, |
||||
field); |
field); |
||||
} |
} |
||||
|
|
||||
export default async (datastore) => { |
export default async (datastore) => { |
||||
|
|
||||
datastore = setupDatastore(datastore); |
datastore = setupDatastore(datastore); |
||||
const templateApi = await getTemplateApi(datastore); |
const templateApi = await getTemplateApi(datastore); |
||||
const addStringField = addField(templateApi)("string"); |
const addStringField = addField(templateApi)("string"); |
||||
const addDateField = addField(templateApi)("datetime"); |
const addDateField = addField(templateApi)("datetime"); |
||||
const addBoolField = addField(templateApi)("bool"); |
const addBoolField = addField(templateApi)("bool"); |
||||
|
|
||||
const root = templateApi.getNewRootLevel(); |
const root = templateApi.getNewRootLevel(); |
||||
|
|
||||
const clients = templateApi.getNewCollectionTemplate(root); |
const clients = templateApi.getNewCollectionTemplate(root); |
||||
clients.name = "clients"; |
clients.name = "clients"; |
||||
|
|
||||
const client = templateApi.getNewRecordTemplate(clients); |
const client = templateApi.getNewRecordTemplate(clients); |
||||
client.name = "client" |
client.name = "client" |
||||
addStringField(client, "FamilyName"); |
addStringField(client, "FamilyName"); |
||||
addStringField(client, "Address1"); |
addStringField(client, "Address1"); |
||||
addStringField(client, "Address2"); |
addStringField(client, "Address2"); |
||||
addStringField(client, "Address3"); |
addStringField(client, "Address3"); |
||||
addStringField(client, "Address4"); |
addStringField(client, "Address4"); |
||||
addStringField(client, "Postcode"); |
addStringField(client, "Postcode"); |
||||
addDateField(client, "CreatedDate"); |
addDateField(client, "CreatedDate"); |
||||
|
|
||||
const children = templateApi.getNewCollectionTemplate(client); |
const children = templateApi.getNewCollectionTemplate(client); |
||||
children.name = "children"; |
children.name = "children"; |
||||
|
|
||||
const child = templateApi.getNewRecordTemplate(children); |
const child = templateApi.getNewRecordTemplate(children); |
||||
child.name = "child"; |
child.name = "child"; |
||||
addStringField(child, "FirstName"); |
addStringField(child, "FirstName"); |
||||
addStringField(child, "Surname"); |
addStringField(child, "Surname"); |
||||
addDateField(child, "DateOfBirth"); |
addDateField(child, "DateOfBirth"); |
||||
addBoolField(child, "Current"); |
addBoolField(child, "Current"); |
||||
|
|
||||
const contacts = templateApi.getNewCollectionTemplate(client); |
const contacts = templateApi.getNewCollectionTemplate(client); |
||||
contacts.name = "contacts"; |
contacts.name = "contacts"; |
||||
|
|
||||
const contact = templateApi.getNewRecordTemplate(contacts); |
const contact = templateApi.getNewRecordTemplate(contacts); |
||||
contact.name = "contact"; |
contact.name = "contact"; |
||||
addStringField(contact, "Name"); |
addStringField(contact, "Name"); |
||||
addStringField(contact, "relationship"); |
addStringField(contact, "relationship"); |
||||
addStringField(contact, "phone1"); |
addStringField(contact, "phone1"); |
||||
addStringField(contact, "phone2"); |
addStringField(contact, "phone2"); |
||||
addBoolField(contact, "active"); |
addBoolField(contact, "active"); |
||||
|
|
||||
await templateApi.saveApplicationHeirarchy(root); |
await templateApi.saveApplicationHeirarchy(root); |
||||
|
|
||||
const apis = await getAppApis(datastore); |
const apis = await getAppApis(datastore); |
||||
|
|
||||
await apis.collectionApi.initialiseAll(); |
await apis.collectionApi.initialiseAll(); |
||||
|
|
||||
return apis; |
return apis; |
||||
|
|
||||
} |
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
File diff suppressed because it is too large
@ -1,8 +1,8 @@ |
|||||
const Koa = require('koa'); |
const Koa = require('koa'); |
||||
const app = new Koa(); |
const app = new Koa(); |
||||
|
|
||||
app.use(async ctx => { |
app.use(async ctx => { |
||||
ctx.body = 'Hello World'; |
ctx.body = 'Hello World'; |
||||
}); |
}); |
||||
|
|
||||
app.listen(3000); |
app.listen(3000); |
||||
@ -1,41 +1,41 @@ |
|||||
const {initialiseData, setupDatastore, |
const {initialiseData, setupDatastore, |
||||
getTemplateApi} = require("budibase-core"); |
getTemplateApi} = require("budibase-core"); |
||||
const {getApisForUser, getDatabaseManager, |
const {getApisForUser, getDatabaseManager, |
||||
getApisWithFullAccess} = require("./helpers"); |
getApisWithFullAccess} = require("./helpers"); |
||||
const masterDbAppDefinition = require("../appPackages/master/appDefinition.json"); |
const masterDbAppDefinition = require("../appPackages/master/appDefinition.json"); |
||||
const masterDbAccessLevels = require("../appPackages/master/access_levels.json"); |
const masterDbAccessLevels = require("../appPackages/master/access_levels.json"); |
||||
|
|
||||
module.exports = async (datastoreModule, rootConfig, username, password) => { |
module.exports = async (datastoreModule, rootConfig, username, password) => { |
||||
try { |
try { |
||||
const databaseManager = getDatabaseManager(datastoreModule, rootConfig); |
const databaseManager = getDatabaseManager(datastoreModule, rootConfig); |
||||
|
|
||||
await databaseManager.createEmptyMasterDb(); |
await databaseManager.createEmptyMasterDb(); |
||||
const masterDbConfig = databaseManager.masterDatastoreConfig; |
const masterDbConfig = databaseManager.masterDatastoreConfig; |
||||
const datastore = setupDatastore( |
const datastore = setupDatastore( |
||||
datastoreModule.getDatastore(masterDbConfig) |
datastoreModule.getDatastore(masterDbConfig) |
||||
); |
); |
||||
|
|
||||
const templateApi = getTemplateApi({datastore}); |
const templateApi = getTemplateApi({datastore}); |
||||
|
|
||||
await initialiseData(datastore, { |
await initialiseData(datastore, { |
||||
heirarchy:templateApi.constructHeirarchy(masterDbAppDefinition.hierarchy), |
heirarchy:templateApi.constructHeirarchy(masterDbAppDefinition.hierarchy), |
||||
actions:masterDbAppDefinition.actions, |
actions:masterDbAppDefinition.actions, |
||||
triggers:masterDbAppDefinition.triggers |
triggers:masterDbAppDefinition.triggers |
||||
}); |
}); |
||||
|
|
||||
const bbMaster = await getApisWithFullAccess(datastore); |
const bbMaster = await getApisWithFullAccess(datastore); |
||||
await bbMaster.authApi.saveAccessLevels(masterDbAccessLevels); |
await bbMaster.authApi.saveAccessLevels(masterDbAccessLevels); |
||||
const user = bbMaster.authApi.getNewUser(); |
const user = bbMaster.authApi.getNewUser(); |
||||
user.name = username; |
user.name = username; |
||||
user.accessLevels= ["owner"]; |
user.accessLevels= ["owner"]; |
||||
await bbMaster.authApi.createUser(user, password); |
await bbMaster.authApi.createUser(user, password); |
||||
|
|
||||
return await getApisForUser(datastore, username, password); |
return await getApisForUser(datastore, username, password); |
||||
} catch(e) { |
} catch(e) { |
||||
throw e; |
throw e; |
||||
} |
} |
||||
}; |
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -1,29 +1,29 @@ |
|||||
const crypto = require("../server/nodeCrypto"); |
const crypto = require("../nodeCrypto"); |
||||
const {getDatabaseManager, getAppApis} = require("budibase-core"); |
const {getDatabaseManager, getAppApis} = require("budibase-core"); |
||||
|
|
||||
module.exports.getApisWithFullAccess = async (datastore) => { |
module.exports.getApisWithFullAccess = async (datastore) => { |
||||
const bb = await getAppApis( |
const bb = await getAppApis( |
||||
datastore, |
datastore, |
||||
null, null, null, |
null, null, null, |
||||
crypto |
crypto |
||||
); |
); |
||||
|
|
||||
bb.withFullAccess(); |
bb.withFullAccess(); |
||||
|
|
||||
return bb; |
return bb; |
||||
}; |
}; |
||||
|
|
||||
module.exports.getApisForUser = async (datastore, username, password) => { |
module.exports.getApisForUser = async (datastore, username, password) => { |
||||
const bb = await getAppApis( |
const bb = await getAppApis( |
||||
datastore, |
datastore, |
||||
null, null, null, |
null, null, null, |
||||
crypto |
crypto |
||||
); |
); |
||||
|
|
||||
await bb.authenticateAs(username, password); |
await bb.authenticateAs(username, password); |
||||
|
|
||||
return bb; |
return bb; |
||||
} |
} |
||||
|
|
||||
module.exports.getDatabaseManager = (datastoreModule, datastoreConfig) => |
module.exports.getDatabaseManager = (datastoreModule, datastoreConfig) => |
||||
getDatabaseManager(datastoreModule.databaseManager(datastoreConfig)); |
getDatabaseManager(datastoreModule.databaseManager(datastoreConfig)); |
||||
@ -1,34 +1,34 @@ |
|||||
|
|
||||
export const budibaseRouting = (options) => { |
export const budibaseRouting = (options) => { |
||||
|
|
||||
return async (ctx, next) => { |
return async (ctx, next) => { |
||||
|
|
||||
ctx.request.path |
ctx.request.path |
||||
|
|
||||
}; |
}; |
||||
|
|
||||
}; |
}; |
||||
|
|
||||
/* api Routes (all /api/..) |
/* api Routes (all /api/..) |
||||
|
|
||||
POST executeAction/<name> {} |
POST executeAction/<name> {} |
||||
POST authenticate {} |
POST authenticate {} |
||||
POST authenticateTemporaryAccess {} |
POST authenticateTemporaryAccess {} |
||||
POST createUser {} |
POST createUser {} |
||||
POST enabledUser {} |
POST enabledUser {} |
||||
POST disableUser {} |
POST disableUser {} |
||||
GET users |
GET users |
||||
GET accessLevels |
GET accessLevels |
||||
POST accessLevels {} |
POST accessLevels {} |
||||
POST changeMyPassword {} |
POST changeMyPassword {} |
||||
POST setPasswordFromTemporaryCode {} |
POST setPasswordFromTemporaryCode {} |
||||
POST listItems/index/key {} |
POST listItems/index/key {} |
||||
POST aggregates/index/key {} |
POST aggregates/index/key {} |
||||
POST record/key/to/rec {} |
POST record/key/to/rec {} |
||||
GET record/key/to/rec |
GET record/key/to/rec |
||||
DELETE record/key/to/rec |
DELETE record/key/to/rec |
||||
POST appHeirarchy {} |
POST appHeirarchy {} |
||||
POST actionsAndTriggers {} |
POST actionsAndTriggers {} |
||||
GET appDefinition |
GET appDefinition |
||||
|
|
||||
*/ |
*/ |
||||
@ -1,41 +1,41 @@ |
|||||
const {getAppApis} = require("budibase-core"); |
const {getAppApis} = require("budibase-core"); |
||||
|
|
||||
module.exports = (datastoreConfig, datastoreModule, method, path) => { |
module.exports = (datastoreConfig, datastoreModule, method, path) => { |
||||
|
|
||||
const datastore = datastoreModule.getDatastore( |
const datastore = datastoreModule.getDatastore( |
||||
datastoreConfig); |
datastoreConfig); |
||||
|
|
||||
const bb = getAppApis( |
const bb = getAppApis( |
||||
datastore |
datastore |
||||
) |
) |
||||
|
|
||||
} |
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/* api Routes (all /api/..) |
/* api Routes (all /api/..) |
||||
|
|
||||
POST executeAction/<name> {} |
POST executeAction/<name> {} |
||||
POST authenticate {} |
POST authenticate {} |
||||
POST authenticateTemporaryAccess {} |
POST authenticateTemporaryAccess {} |
||||
POST createUser {} |
POST createUser {} |
||||
POST enabledUser {} |
POST enabledUser {} |
||||
POST disableUser {} |
POST disableUser {} |
||||
GET users |
GET users |
||||
GET accessLevels |
GET accessLevels |
||||
POST accessLevels {} |
POST accessLevels {} |
||||
POST changeMyPassword {} |
POST changeMyPassword {} |
||||
POST setPasswordFromTemporaryCode {} |
POST setPasswordFromTemporaryCode {} |
||||
POST listItems/index/key {} |
POST listItems/index/key {} |
||||
POST aggregates/index/key {} |
POST aggregates/index/key {} |
||||
POST record/key/to/rec {} |
POST record/key/to/rec {} |
||||
GET record/key/to/rec |
GET record/key/to/rec |
||||
DELETE record/key/to/rec |
DELETE record/key/to/rec |
||||
POST appHeirarchy {} |
POST appHeirarchy {} |
||||
POST actionsAndTriggers {} |
POST actionsAndTriggers {} |
||||
GET appDefinition |
GET appDefinition |
||||
|
|
||||
*/ |
*/ |
||||
@ -1,5 +1,5 @@ |
|||||
const {hash, verify} = require("argon2"); |
const {hash, verify} = require("argon2"); |
||||
|
|
||||
module.exports = { |
module.exports = { |
||||
hash, verify |
hash, verify |
||||
}; |
}; |
||||
@ -0,0 +1,20 @@ |
|||||
|
{ |
||||
|
"name": "budibase", |
||||
|
"version": "0.0.1", |
||||
|
"description": "budibase wrapper repo for development", |
||||
|
"main": "index.js", |
||||
|
"scripts": { |
||||
|
"test": "echo \"Error: no test specified\" && exit 1" |
||||
|
}, |
||||
|
"keywords": [ |
||||
|
"budibase" |
||||
|
], |
||||
|
"author": "Michael Shanks", |
||||
|
"license": "AGPL-3.0-or-later", |
||||
|
"dependencies": { |
||||
|
"argon2": "^0.23.0", |
||||
|
"budibase-core": "file:../budibase-core/dist", |
||||
|
"rimraf": "^2.6.3", |
||||
|
"yargs": "^13.2.4" |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -1,73 +0,0 @@ |
|||||
# Logs |
|
||||
logs |
|
||||
*.log |
|
||||
npm-debug.log* |
|
||||
yarn-debug.log* |
|
||||
yarn-error.log* |
|
||||
|
|
||||
# Runtime data |
|
||||
pids |
|
||||
*.pid |
|
||||
*.seed |
|
||||
*.pid.lock |
|
||||
|
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover |
|
||||
lib-cov |
|
||||
|
|
||||
# Coverage directory used by tools like istanbul |
|
||||
coverage |
|
||||
|
|
||||
# nyc test coverage |
|
||||
.nyc_output |
|
||||
|
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) |
|
||||
.grunt |
|
||||
|
|
||||
# Bower dependency directory (https://bower.io/) |
|
||||
bower_components |
|
||||
|
|
||||
# node-waf configuration |
|
||||
.lock-wscript |
|
||||
|
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html) |
|
||||
build/Release |
|
||||
|
|
||||
# Dependency directories |
|
||||
node_modules/ |
|
||||
jspm_packages/ |
|
||||
|
|
||||
# TypeScript v1 declaration files |
|
||||
typings/ |
|
||||
|
|
||||
# Optional npm cache directory |
|
||||
.npm |
|
||||
|
|
||||
# Optional eslint cache |
|
||||
.eslintcache |
|
||||
|
|
||||
# Optional REPL history |
|
||||
.node_repl_history |
|
||||
|
|
||||
# Output of 'npm pack' |
|
||||
*.tgz |
|
||||
|
|
||||
# Yarn Integrity file |
|
||||
.yarn-integrity |
|
||||
|
|
||||
# dotenv environment variables file |
|
||||
.env |
|
||||
|
|
||||
# parcel-bundler cache (https://parceljs.org/) |
|
||||
.cache |
|
||||
|
|
||||
# next.js build output |
|
||||
.next |
|
||||
|
|
||||
# nuxt.js build output |
|
||||
.nuxt |
|
||||
|
|
||||
# vuepress build output |
|
||||
.vuepress/dist |
|
||||
|
|
||||
# Serverless directories |
|
||||
.serverless |
|
||||
@ -1,19 +0,0 @@ |
|||||
{ |
|
||||
"name": "budibase-server", |
|
||||
"version": "0.0.1", |
|
||||
"description": "budibase http api", |
|
||||
"main": "index.js", |
|
||||
"scripts": { |
|
||||
"test": "echo \"Error: no test specified\" && exit 1", |
|
||||
"build-core": "cd ./node_modules/budibase-core && rollup --config rollup.config.js" |
|
||||
}, |
|
||||
"keywords": [ |
|
||||
"budibase" |
|
||||
], |
|
||||
"author": "Michael Shanks", |
|
||||
"license": "ISC", |
|
||||
"dependencies": { |
|
||||
"budibase-core": "git+ssh://git@gitlab.com/budibase-dist/budibase-core.git", |
|
||||
"koa": "^2.7.0" |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue