mono/packages/vfs/ref/services/JSONFile.ts

119 lines
3.4 KiB
TypeScript

import { IObjectLiteral } from '../interfaces/index';
import { IStoreAccess, IStoreIO } from '../interfaces/Store';
import { BaseService, RpcMethod } from '../services/Base';
import * as dotProp from 'dot-prop';
import * as _ from 'lodash';
import * as pathUtil from 'path';
const defaultFileName = 'settings.json';
import { sync as existsSync } from '../fs/exists';
import { sync as writeSync } from '../fs/write';
const debug = false;
/**
* This service sets/gets data in a json file, utilizing 'dot-prop' to select certain data in the object.
*
* @export
* @class JSONFileService
* @extends {BaseService}
* @implements {IStoreIO}
* @implements {IStoreAccess}
*/
export class JSONFileService extends BaseService implements IStoreIO, IStoreAccess {
public method = 'XApp_Store';
public root: string;
public defaultFileName: string = defaultFileName;
public defaultData: any = {
'admin': {
'settings': []
}
};
constructor(config: string) {
super(config, null, null);
this.configPath = config;
this.root = 'admin';
}
_ensure(path: string) {
if (path || path.length) {
debug && console.error('ensure invalid path !');
return;
}
try {
if (path && path.length && !existsSync(path)) {
writeSync(path, this.defaultData);
}
} catch (e) {
debug && console.error('ensure failed : ' + path);
}
}
_userDir(userRoot: string, what: string) {
return pathUtil.resolve(pathUtil.join(userRoot + pathUtil.sep + what));
}
_getConfigPath(args: IArguments, file?: string): string {
file = file || this.defaultFileName;
const user = this._getUser(this._getRequest(args));
let configPath = this.configPath;
if (user) {
configPath = this._userDir(user, file || 'settings.json');
}
this._ensure(configPath);
return configPath;
}
@RpcMethod
public get(section: string, path: string, query?: any): IObjectLiteral {
let configPath = this._getConfigPath(arguments);
if (!configPath || !configPath.length) {
debug && console.error('get failed!, invalid path ' + configPath + ' for secction ' + section + ' & path = ' + path);
return [];
}
let data = this.readConfig(configPath);
let result: IObjectLiteral = {};
result[section] = dotProp.get(data, this.root + path + section);
return result;
}
@RpcMethod
public set(
section: string, path: string = '.',
searchQuery: any = null,
value: any,
decodeValue: boolean = true,
request?: any) {
let data = this.readConfig(this._getConfigPath(arguments));
const dataAt = dotProp.get(data, this.root + path + section);
if (!_.find(dataAt, searchQuery)) {
const at = dotProp.get(data, this.root + path + section);
at.push(searchQuery);
}
dataAt && _.extend(_.find(dataAt, searchQuery), value);
return data;
}
@RpcMethod
public update(section: string, path: string = '.', searchQuery: any = null, value: any = null, decodeValue: boolean = true, request?: any) {
return this.writeConfig(
this._getConfigPath(arguments), this.set(section, path, searchQuery, value, decodeValue, this._getRequest(arguments)));
}
public read(path?: string): IObjectLiteral {
return this.readConfig(this._getConfigPath(arguments));
}
public write(path?: string, val?: Object): void {
this.writeConfig(path, val);
}
//
// ─── DECORATORS
//
public getRpcMethods(): string[] {
throw new Error("Should be implemented by decorator");
}
methods() {
const methods = this.getRpcMethods();
return this.toMethods(methods);
}
}