add server to monorepo.

This commit is contained in:
a.bouhuolia
2023-02-03 11:57:50 +02:00
parent 28e309981b
commit 80b97b5fdc
1303 changed files with 137049 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
export default class BudgetEntriesSet {
constructor() {
this.accounts = {};
this.totalSummary = {}
this.orderSize = null;
}
setZeroPlaceholder() {
if (!this.orderSize) { return; }
Object.values(this.accounts).forEach((account) => {
for (let i = 0; i <= this.orderSize.length; i++) {
if (typeof account[i] === 'undefined') {
account[i] = { amount: 0 };
}
}
});
}
static from(accounts, configs) {
const collection = new this(configs);
accounts.forEach((entry) => {
if (typeof this.accounts[entry.accountId] === 'undefined') {
collection.accounts[entry.accountId] = {};
}
if (entry.order) {
collection.accounts[entry.accountId][entry.order] = entry;
}
});
return collection;
}
toArray() {
const output = [];
Object.key(this.accounts).forEach((accountId) => {
const entries = this.accounts[accountId];
output.push({
account_id: accountId,
entries: [
...Object.key(entries).map((order) => {
const entry = entries[order];
return {
order,
amount: entry.amount,
};
}),
],
});
});
}
calcTotalSummary() {
const totalSummary = {};
for (let i = 0; i < this.orderSize.length; i++) {
Object.value(this.accounts).forEach((account) => {
if (typeof totalSummary[i] !== 'undefined') {
totalSummary[i] = { amount: 0, order: i };
}
totalSummary[i].amount += account[i].amount;
});
}
this.totalSummary = totalSummary;
}
toArrayTotalSummary() {
return Object.values(this.totalSummary);
}
}

View File

@@ -0,0 +1,279 @@
export default {
METADATA_GROUP: 'default',
KEY_COLUMN: 'key',
VALUE_COLUMN: 'value',
TYPE_COLUMN: 'type',
extraColumns: [],
metadata: [],
shouldReload: true,
extraMetadataQuery: () => {},
/**
* Set the value column key to query from.
* @param {String} name -
*/
setKeyColumnName(name) {
this.KEY_COLUMN = name;
},
/**
* Set the key column name to query from.
* @param {String} name -
*/
setValueColumnName(name) {
this.VALUE_COLUMN = name;
},
/**
* Set extra columns to be added to the rows.
* @param {Array} columns -
*/
setExtraColumns(columns) {
this.extraColumns = columns;
},
/**
* Metadata database query.
* @param {Object} query -
* @param {String} groupName -
*/
whereQuery(query, key) {
const groupName = this.METADATA_GROUP;
if (groupName) {
query.where('group', groupName);
}
if (key) {
if (Array.isArray(key)) {
query.whereIn('key', key);
} else {
query.where('key', key);
}
}
},
/**
* Loads the metadata from the storage.
* @param {String|Array} key -
* @param {Boolean} force -
*/
async load(force = false) {
if (this.shouldReload || force) {
const metadataCollection = await this.query((query) => {
this.whereQuery(query);
this.extraMetadataQuery(query);
}).fetchAll();
this.shouldReload = false;
this.metadata = [];
const metadataArray = this.mapMetadataCollection(metadataCollection);
metadataArray.forEach((metadata) => { this.metadata.push(metadata); });
}
},
/**
* Fetches all the metadata that associate with the current group.
*/
async allMeta(force = false) {
await this.load(force);
return this.metadata;
},
/**
* Find the given metadata key.
* @param {String} key -
* @return {object} - Metadata object.
*/
findMeta(key) {
return this.metadata.find((meta) => meta.key === key);
},
/**
* Fetch the metadata of the current group.
* @param {*} key -
*/
async getMeta(key, defaultValue, force = false) {
await this.load(force);
const metadata = this.findMeta(key);
return metadata ? metadata.value : defaultValue || false;
},
/**
* Markes the metadata to should be deleted.
* @param {String} key -
*/
async removeMeta(key) {
await this.load();
const metadata = this.findMeta(key);
if (metadata) {
metadata.markAsDeleted = true;
}
this.shouldReload = true;
/**
* Remove all meta data of the given group.
* @param {*} group
*/
removeAllMeta(group = 'default') {
this.metdata.map((meta) => ({
...(meta.group !== group) ? { markAsDeleted: true } : {},
...meta,
}));
this.shouldReload = true;
},
/**
* Set the meta data to the stack.
* @param {String} key -
* @param {String} value -
*/
async setMeta(key, value, payload) {
if (Array.isArray(key)) {
const metadata = key;
metadata.forEach((meta) => {
this.setMeta(meta.key, meta.value);
});
return;
}
await this.load();
const metadata = this.findMeta(key);
if (metadata) {
metadata.value = value;
metadata.markAsUpdated = true;
} else {
this.metadata.push({
value, key, ...payload, markAsInserted: true,
});
}
},
/**
* Saved the modified metadata.
*/
async saveMeta() {
const inserted = this.metadata.filter((m) => (m.markAsInserted === true));
const updated = this.metadata.filter((m) => (m.markAsUpdated === true));
const deleted = this.metadata.filter((m) => (m.markAsDeleted === true));
const metadataDeletedKeys = deleted.map((m) => m.key);
const metadataInserted = inserted.map((m) => this.mapMetadata(m, 'format'));
const metadataUpdated = updated.map((m) => this.mapMetadata(m, 'format'));
const batchUpdate = (collection) => knex.transaction((trx) => {
const queries = collection.map((tuple) => {
const query = knex(this.tableName);
this.whereQuery(query, tuple.key);
this.extraMetadataQuery(query);
return query.update(tuple).transacting(trx);
});
return Promise.all(queries).then(trx.commit).catch(trx.rollback);
});
await Promise.all([
knex.insert(metadataInserted).into(this.tableName),
batchUpdate(metadataUpdated),
metadataDeletedKeys.length > 0
? this.query('whereIn', this.KEY_COLUMN, metadataDeletedKeys).destroy({
require: true,
}) : null,
]);
this.shouldReload = true;
},
/**
* Purge all the cached metadata in the memory.
*/
purgeMetadata() {
this.metadata = [];
this.shouldReload = true;
},
/**
* Parses the metadata value.
* @param {String} value -
* @param {String} valueType -
*/
parseMetaValue(value, valueType) {
let parsedValue;
switch (valueType) {
case 'integer':
parsedValue = parseInt(value, 10);
break;
case 'float':
parsedValue = parseFloat(value);
break;
case 'boolean':
parsedValue = Boolean(value);
break;
case 'json':
parsedValue = JSON.parse(parsedValue);
break;
default:
parsedValue = value;
break;
}
return parsedValue;
},
/**
* Format the metadata before saving to the database.
* @param {String|Number|Boolean} value -
* @param {String} valueType -
* @return {String|Number|Boolean} -
*/
formatMetaValue(value, valueType) {
let parsedValue;
switch (valueType) {
case 'number':
parsedValue = `${value}`;
break;
case 'boolean':
parsedValue = value ? '1' : '0';
break;
case 'json':
parsedValue = JSON.stringify(parsedValue);
break;
default:
parsedValue = value;
break;
}
return parsedValue;
},
mapMetadata(attr, parseType = 'parse') {
return {
key: attr[this.KEY_COLUMN],
value: (parseType === 'parse')
? this.parseMetaValue(
attr[this.VALUE_COLUMN],
this.TYPE_COLUMN ? attr[this.TYPE_COLUMN] : false,
)
: this.formatMetaValue(
attr[this.VALUE_COLUMN],
this.TYPE_COLUMN ? attr[this.TYPE_COLUMN] : false,
),
...this.extraColumns.map((extraCol) => ({
[extraCol]: attr[extraCol] || null,
})),
};
},
/**
* Parse the metadata collection.
* @param {Array} collection -
*/
mapMetadataCollection(collection, parseType = 'parse') {
return collection.map((model) => this.mapMetadata(model.attributes, parseType));
},
};

View File

@@ -0,0 +1,116 @@
export default class NestedSet {
/**
* Constructor method.
* @param {Object} options -
*/
constructor(items, options) {
this.options = {
parentId: 'parent_id',
id: 'id',
...options,
};
this.items = items || [];
this.tree = this.linkChildren();
}
setItems(items) {
this.items = items;
this.tree = this.linkChildren();
}
/**
* Link nodes children.
*/
linkChildren() {
if (this.items.length <= 0) return false;
const map = {};
this.items.forEach((item) => {
map[item.id] = item;
map[item.id].children = {};
});
this.items.forEach((item) => {
const parentNodeId = item[this.options.parentId];
if (parentNodeId) {
map[parentNodeId].children[item.id] = item;
}
});
return map;
}
toArray() {
const stack = [];
const treeNodes = this.items.map((i) => ({ ...i }));
const walk = (nodes) => {
nodes.forEach((node) => {
if (!node[this.options.parentId]) {
stack.push(node);
}
if (node.children) {
const childrenNodes = Object.values(node.children)
.map((i) => ({ ...i }));
node.children = childrenNodes;
walk(childrenNodes);
}
});
};
walk(treeNodes);
return stack;
}
getTree() {
return this.tree;
}
getElementById(id) {
return this.tree[id] || null
}
getParents(id) {
const item = this.getElementById(id);
const parents = [];
let index = 0;
const walk = (_item) => {
if (!item) return;
if (index) {
parents.push(_item);
}
if (_item[this.options.parentId]) {
const parentItem = this.getElementById(_item[this.options.parentId]);
index++;
walk(parentItem);
}
};
walk(item);
return parents;
}
toFlattenArray(nodeMapper) {
const flattenTree = [];
const traversal = (nodes, parentNode) => {
nodes.forEach((node) => {
let nodeMapped = node;
if (typeof nodeMapper === 'function') {
nodeMapped = nodeMapper(nodeMapped, parentNode);
}
flattenTree.push(nodeMapped);
if (node.children && node.children.length > 0) {
traversal(node.children, node);
}
});
};
traversal(this.collection);
return flattenTree;
}
}

View File

@@ -0,0 +1,14 @@
import MetableCollection from '@/lib/Metable/MetableCollection';
import ResourceFieldMetadata from 'models/ResourceFieldMetadata';
export default class ResourceFieldMetadataCollection extends MetableCollection {
/**
* Constructor method.
*/
constructor() {
super();
this.setModel(ResourceFieldMetadata);
this.extraColumns = ['resource_id', 'resource_item_id'];
}
}

View File

@@ -0,0 +1,73 @@
import moment from 'moment';
import { Model } from 'objection';
const options = {
columnName: 'deleted_at',
deletedValue: moment().format('YYYY-MM-DD HH:mm:ss'),
notDeletedValue: null,
};
export default class SoftDeleteQueryBuilder extends Model.QueryBuilder {
constructor(...args) {
super(...args);
this.onBuild((builder) => {
if (builder.isFind() || builder.isDelete() || builder.isUpdate()) {
builder.whereNotDeleted();
}
});
}
/**
* override the normal delete function with one that patches the row's "deleted" column
*/
delete() {
this.context({
softDelete: true,
});
const patch = {};
patch[options.columnName] = options.deletedValue;
return this.patch(patch);
}
/**
* Provide a way to actually delete the row if necessary
*/
hardDelete() {
return super.delete();
}
/**
* Provide a way to undo the delete
*/
undelete() {
this.context({
undelete: true,
});
const patch = {};
patch[options.columnName] = options.notDeletedValue;
return this.patch(patch);
}
/**
* Provide a way to filter to ONLY deleted records without having to remember the column name
*/
whereDeleted() {
const prefix = this.modelClass().tableName;
// this if is for backwards compatibility, to protect those that used a nullable `deleted` field
if (options.deletedValue === true) {
return this.where(`${prefix}.${options.columnName}`, options.deletedValue);
}
// qualify the column name
return this.whereNot(`${prefix}.${options.columnName}`, options.notDeletedValue);
}
// provide a way to filter out deleted records without having to remember the column name
whereNotDeleted() {
const prefix = this.modelClass().tableName;
// qualify the column name
return this.where(`${prefix}.${options.columnName}`, options.notDeletedValue);
}
}