Initial Commit ...
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,622 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
const XDecoratorDescriptor = require('./x-decorator.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is ClassDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result =
|
||||
object.hasOwnProperty('raw') &&
|
||||
Array.isArray(object.extends) &&
|
||||
object.hasOwnProperty('name') &&
|
||||
Array.isArray(object.implements) &&
|
||||
object.hasOwnProperty('extends') &&
|
||||
object.hasOwnProperty('isPublic') &&
|
||||
object.hasOwnProperty('decorator') &&
|
||||
object.hasOwnProperty('implements') &&
|
||||
object.hasOwnProperty('isExported') &&
|
||||
object.hasOwnProperty('isExtended') &&
|
||||
object.hasOwnProperty('isAbstract') &&
|
||||
object.hasOwnProperty('hasDecorator') &&
|
||||
object.hasOwnProperty('isImplemented');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled ClassDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of ClassDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
const result = {
|
||||
raw: '',
|
||||
name: '',
|
||||
extends: [],
|
||||
implements: [],
|
||||
isPublic: true,
|
||||
isExported: false,
|
||||
isExtended: false,
|
||||
isAbstract: false,
|
||||
hasDecorator: false,
|
||||
isImplemented: false,
|
||||
decorator: {
|
||||
...XDecoratorDescriptor.createDescriptor()
|
||||
},
|
||||
};
|
||||
|
||||
//
|
||||
//#region Apply Props ...
|
||||
if (value) {
|
||||
//
|
||||
//#region name ...
|
||||
if (XValueTools.isValidArg(value.name)) {
|
||||
result.name = value.name;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region extends ...
|
||||
if (XValueTools.hasChildArray(value.extends)) {
|
||||
result.extends = [...value.extends];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region implements ...
|
||||
if (XValueTools.hasChildArray(value.implements)) {
|
||||
result.implements = [...value.implements];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region raw ...
|
||||
if (XValueTools.isValidArg(value.raw)) {
|
||||
result.raw = value.raw;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isPublic ...
|
||||
if (!!value.isPublic) {
|
||||
result.isPublic = true;
|
||||
} else if (value.isPublic === false) {
|
||||
result.isPublic = false;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isExported ...
|
||||
if (!!value.isExported) {
|
||||
result.isExported = true;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isExtended ...
|
||||
if (!!value.isExtended) {
|
||||
result.isExtended = true;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isAbstract ...
|
||||
if (!!value.isAbstract) {
|
||||
result.isAbstract = true;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region hasDecorator ...
|
||||
if (!!value.hasDecorator) {
|
||||
result.hasDecorator = true;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region decorator ...
|
||||
if (!!result.hasDecorator && value.decorator) {
|
||||
result.decorator = {
|
||||
...XDecoratorDescriptor.createDescriptor(value.decorator)
|
||||
};
|
||||
} else {
|
||||
result.decorator = undefined;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isImplemented ...
|
||||
if (!!value.isImplemented) {
|
||||
result.isImplemented = true;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of ClassDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(
|
||||
descriptor = createDescriptor(),
|
||||
forceClearContent = false,
|
||||
) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
let classContent = '';
|
||||
let classContentIndexers = XValueTools.findClosedContent('{', '}', descriptor.raw);
|
||||
if (XValueTools.hasChildArray(classContentIndexers)) {
|
||||
//
|
||||
classContent = XValueTools
|
||||
.clearObjectSurround(classContentIndexers[0].content);
|
||||
|
||||
//
|
||||
if (!!forceClearContent) {
|
||||
classContent = XBaseDescriptor.clearContent(classContent);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Handle Class Decorator ...
|
||||
if (
|
||||
!!descriptor.hasDecorator &&
|
||||
XValueTools.isValidArgs(descriptor.decorator.type) &&
|
||||
XBaseDescriptor.isValidDecoratorType(descriptor.decorator.type)
|
||||
) {
|
||||
//
|
||||
result += XDecoratorDescriptor
|
||||
.toExpression(descriptor.decorator) +
|
||||
'\n';
|
||||
}
|
||||
|
||||
//
|
||||
// Handle Class ...
|
||||
result +=
|
||||
//
|
||||
// Export ...
|
||||
(
|
||||
descriptor.isExported ?
|
||||
XBaseDescriptor.ExpressionKeys.Export +
|
||||
' ' :
|
||||
''
|
||||
) +
|
||||
//
|
||||
// Public or Private ...
|
||||
(
|
||||
!descriptor.isPublic ?
|
||||
XBaseDescriptor.ExpressionKeys.Private +
|
||||
' ' :
|
||||
''
|
||||
) +
|
||||
//
|
||||
// Abstract ...
|
||||
(
|
||||
descriptor.isAbstract ?
|
||||
XBaseDescriptor.ExpressionKeys.Abstract +
|
||||
' ' :
|
||||
''
|
||||
) +
|
||||
//
|
||||
// Class Definition ...
|
||||
XBaseDescriptor.ExpressionKeys.Class +
|
||||
' ' +
|
||||
descriptor.name +
|
||||
' ' +
|
||||
//
|
||||
// Extends ...
|
||||
(
|
||||
descriptor.isExtended ?
|
||||
XBaseDescriptor.ExpressionKeys.Extends +
|
||||
' ' +
|
||||
descriptor.extends.join(', ')
|
||||
+ ' ' :
|
||||
''
|
||||
) +
|
||||
//
|
||||
// Implements ...
|
||||
(
|
||||
descriptor.isImplemented ?
|
||||
XBaseDescriptor.ExpressionKeys.Implements +
|
||||
' ' +
|
||||
descriptor.implements.join(', ') +
|
||||
' ' :
|
||||
''
|
||||
) +
|
||||
//
|
||||
// Open Class ...
|
||||
'{\n' +
|
||||
//
|
||||
// Class Content ...
|
||||
(
|
||||
XValueTools.isValidArg(classContent) ?
|
||||
classContent :
|
||||
''
|
||||
) +
|
||||
//
|
||||
// Close Class ...
|
||||
'\n}';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ClassDescriptors ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of ClassDescriptors ...
|
||||
*/
|
||||
async function extractDescriptors(file = '') {
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
result = extractDescriptorsFromContent(fileContent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ClassDescriptors ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of ClassDescriptors ...
|
||||
*/
|
||||
function extractDescriptorsFromContent(content = '') {
|
||||
//
|
||||
// Prepare result ...
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(content) ||
|
||||
!content.includes(XBaseDescriptor.ExpressionKeys.Class)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract all Key Indexes ...
|
||||
const keyIndexes = XBaseDescriptor.
|
||||
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Class, content);
|
||||
|
||||
//
|
||||
// Validate Keys Exists on Content ...
|
||||
if (!XValueTools.hasChildArray(keyIndexes)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through indexes ...
|
||||
for (let index of keyIndexes) {
|
||||
//
|
||||
// create an empty instance of descriptor ...
|
||||
let descriptor = {
|
||||
...createDescriptor()
|
||||
}
|
||||
|
||||
//
|
||||
let startIndex = index;
|
||||
let endIndex = content.indexOf('{', startIndex);
|
||||
let rawIndexContents = XValueTools.findClosedContent('{', '}', content, endIndex);
|
||||
if (!XValueTools.hasChildArray(rawIndexContents)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
let identifier = content.substring(
|
||||
index + XBaseDescriptor.ExpressionKeys.Class.length,
|
||||
endIndex
|
||||
).trim();
|
||||
|
||||
//
|
||||
//#region HasExtends, Extends, HasImplements, Implements ...
|
||||
//
|
||||
const hasExtends = identifier.includes(XBaseDescriptor.ExpressionKeys.Extends);
|
||||
const hasImplements = identifier.includes(XBaseDescriptor.ExpressionKeys.Implements);
|
||||
|
||||
//
|
||||
descriptor.isExtended = hasExtends;
|
||||
descriptor.isImplemented = hasImplements;
|
||||
|
||||
//
|
||||
let extendsStartIndex = -1;
|
||||
let implementsStartIndex = -1;
|
||||
|
||||
//
|
||||
// Extends ...
|
||||
if (!!hasExtends) {
|
||||
//
|
||||
extendsStartIndex = identifier
|
||||
.indexOf(XBaseDescriptor.ExpressionKeys.Extends) +
|
||||
XBaseDescriptor.ExpressionKeys.Extends.length;
|
||||
|
||||
//
|
||||
let extendsIdentifier = identifier
|
||||
.substring(extendsStartIndex)
|
||||
.trim();
|
||||
if (extendsIdentifier
|
||||
.includes(XBaseDescriptor.ExpressionKeys.Implements)) {
|
||||
//
|
||||
let extendsEndIndex = extendsIdentifier
|
||||
.indexOf(XBaseDescriptor.ExpressionKeys.Implements);
|
||||
extendsIdentifier = extendsIdentifier
|
||||
.substring(0, extendsEndIndex)
|
||||
.trim();
|
||||
}
|
||||
|
||||
//
|
||||
// Continue if it's not Valid ...
|
||||
if (!XValueTools.isValidArg(extendsIdentifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if extends is Array or not ...
|
||||
if (extendsIdentifier.includes(',')) {
|
||||
descriptor.extends.push(
|
||||
...extendsIdentifier
|
||||
.split(',')
|
||||
.map(e => e.trim())
|
||||
.filter(e => XValueTools.isValidArg(e))
|
||||
)
|
||||
} else {
|
||||
descriptor.extends.push(extendsIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Implements ...
|
||||
if (!!hasImplements) {
|
||||
//
|
||||
implementsStartIndex = identifier
|
||||
.indexOf(XBaseDescriptor.ExpressionKeys.Implements) +
|
||||
XBaseDescriptor.ExpressionKeys.Implements.length;
|
||||
|
||||
//
|
||||
let implementsIdentifier = identifier
|
||||
.substring(implementsStartIndex)
|
||||
.trim();
|
||||
if (implementsIdentifier
|
||||
.includes(XBaseDescriptor.ExpressionKeys.Extends)) {
|
||||
//
|
||||
let implementsEndIndex = implementsIdentifier
|
||||
.indexOf(XBaseDescriptor.ExpressionKeys.Extends);
|
||||
implementsIdentifier = implementsIdentifier
|
||||
.substring(0, implementsEndIndex)
|
||||
.trim();
|
||||
}
|
||||
|
||||
//
|
||||
// Continue if it's not Valid ...
|
||||
if (!XValueTools.isValidArg(implementsIdentifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if extends is Array or not ...
|
||||
if (implementsIdentifier.includes(',')) {
|
||||
descriptor.implements.push(
|
||||
...implementsIdentifier
|
||||
.split(',')
|
||||
.map(i => i.trim())
|
||||
.filter(i => XValueTools.isValidArg(i))
|
||||
)
|
||||
} else {
|
||||
descriptor.implements.push(implementsIdentifier);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Class Name ...
|
||||
let nameEndIndex = Math.min(
|
||||
...[
|
||||
extendsStartIndex,
|
||||
implementsStartIndex,
|
||||
identifier.length
|
||||
]
|
||||
.filter(i => i >= 0)
|
||||
);
|
||||
identifier = identifier
|
||||
.substring(0, nameEndIndex)
|
||||
.replace(XBaseDescriptor.ExpressionKeys.Extends, '')
|
||||
.replace(XBaseDescriptor.ExpressionKeys.Implements, '')
|
||||
.trim();
|
||||
|
||||
//
|
||||
// Continue if class name is not valid ...
|
||||
if (!XValueTools.isValidArg(identifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Descriptor name ...
|
||||
descriptor.name = identifier;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Exported, Public, Abstract ...
|
||||
//
|
||||
const lengthForComeBack =
|
||||
XBaseDescriptor.ExpressionKeys.Export.length +
|
||||
XBaseDescriptor.ExpressionKeys.Public.length +
|
||||
XBaseDescriptor.ExpressionKeys.Private.length +
|
||||
XBaseDescriptor.ExpressionKeys.Abstract.length;
|
||||
|
||||
//
|
||||
startIndex = index - lengthForComeBack;
|
||||
endIndex = index;
|
||||
identifier = content
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
// Exported ...
|
||||
descriptor.isExported = identifier.includes(XBaseDescriptor.ExpressionKeys.Export);
|
||||
|
||||
//
|
||||
// Public ...
|
||||
descriptor.isPublic = identifier.includes(XBaseDescriptor.ExpressionKeys.Public) ||
|
||||
!identifier.includes(XBaseDescriptor.ExpressionKeys.Private);
|
||||
|
||||
//
|
||||
// Abstract ...
|
||||
descriptor.isAbstract = identifier.includes(XBaseDescriptor.ExpressionKeys.Abstract);
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Raw ...
|
||||
let classStartIndex = Math.max(
|
||||
...[
|
||||
content.indexOf(XBaseDescriptor.ExpressionKeys.Export, startIndex),
|
||||
content.indexOf(XBaseDescriptor.ExpressionKeys.Public, startIndex),
|
||||
content.indexOf(XBaseDescriptor.ExpressionKeys.Private, startIndex),
|
||||
content.indexOf(XBaseDescriptor.ExpressionKeys.Abstract, startIndex),
|
||||
]
|
||||
.filter(i => i >= 0 && i <= rawIndexContents[0].start)
|
||||
);
|
||||
let classEndIndex = rawIndexContents[0].end + 1;
|
||||
descriptor.raw = content.substring(classStartIndex, classEndIndex);
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Decorator ...
|
||||
//
|
||||
const forExtractDecoratorContentEndIndex = content.indexOf(descriptor.raw);
|
||||
let forExtractDecoratorContent = content.substring(0, forExtractDecoratorContentEndIndex);
|
||||
|
||||
//
|
||||
let decoratorIndexes = XValueTools
|
||||
.findAllIndexes('@(.*)\\({', forExtractDecoratorContent)
|
||||
.map(index => {
|
||||
return {
|
||||
startIndex: index,
|
||||
decoratorContentIndexer: XValueTools
|
||||
.findClosedContent('({', '})', forExtractDecoratorContent, index)[0]
|
||||
}
|
||||
});
|
||||
let decoratorIndex = decoratorIndexes
|
||||
.find(i => i.decoratorContentIndexer.end + 1 === classStartIndex - 1);
|
||||
if (
|
||||
!decoratorIndex &&
|
||||
decoratorIndexes.length === 1 &&
|
||||
XValueTools.hasChildArray(decoratorIndexes)
|
||||
) {
|
||||
//
|
||||
decoratorIndex = {
|
||||
//
|
||||
...decoratorIndexes[0],
|
||||
|
||||
//
|
||||
decoratorContentIndexer: {
|
||||
//
|
||||
...decoratorIndexes[0]
|
||||
.decoratorContentIndexer,
|
||||
|
||||
//
|
||||
end: classStartIndex - 1,
|
||||
|
||||
//
|
||||
content: content.substring(
|
||||
decoratorIndexes[0]
|
||||
.decoratorContentIndexer
|
||||
.start,
|
||||
classStartIndex - 1
|
||||
),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
if (decoratorIndex) {
|
||||
//
|
||||
identifier = forExtractDecoratorContent
|
||||
.substring(
|
||||
decoratorIndex.startIndex,
|
||||
decoratorIndex.decoratorContentIndexer.end + 1
|
||||
);
|
||||
|
||||
//
|
||||
const decorator = XDecoratorDescriptor.extractDescriptorFromContent(identifier);
|
||||
if (!decorator) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
descriptor.hasDecorator = true;
|
||||
descriptor.decorator = {
|
||||
...decorator
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptors,
|
||||
extractDescriptorsFromContent,
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
const XContentDescriptor = require('./x-content.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is ConstDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result =
|
||||
object.hasOwnProperty('raw') &&
|
||||
object.hasOwnProperty('name') &&
|
||||
object.hasOwnProperty('content') &&
|
||||
object.hasOwnProperty('isExported');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled ConstDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of ConstDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
raw: '',
|
||||
name: '',
|
||||
type: '',
|
||||
content: {
|
||||
...XContentDescriptor.createDescriptor()
|
||||
},
|
||||
isExported: false,
|
||||
};
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region raw ...
|
||||
if (XValueTools.isValidArg(value.raw)) {
|
||||
result.raw = value.raw;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region name ...
|
||||
if (XValueTools.isValidArg(value.name)) {
|
||||
result.name = value.name;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region type ...
|
||||
if (XValueTools.isValidArg(value.type)) {
|
||||
result.type = value.type;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region content ...
|
||||
if (
|
||||
value.content &&
|
||||
XContentDescriptor.isDescriptor(value.content)
|
||||
) {
|
||||
result.content = { ...value.content };
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isExported ...
|
||||
if (!!value.isExported) {
|
||||
result.isExported = value.isExported;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of ConstDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(descriptor = createDescriptor()) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result += (
|
||||
!!descriptor.isExported ?
|
||||
XBaseDescriptor.ExpressionKeys.Export + ' ' :
|
||||
''
|
||||
) +
|
||||
XBaseDescriptor.ExpressionKeys.Const +
|
||||
' ' +
|
||||
descriptor.name +
|
||||
(
|
||||
XValueTools.isValidArg(descriptor.type) ?
|
||||
': ' +
|
||||
descriptor.type :
|
||||
''
|
||||
) +
|
||||
' = ';
|
||||
|
||||
//
|
||||
let contentExpression = XContentDescriptor.toExpression(descriptor.content, ':');
|
||||
if (XValueTools.isValidArg(contentExpression)) {
|
||||
result += contentExpression;
|
||||
}
|
||||
|
||||
//
|
||||
result += ';';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ConstDescriptors ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of ConstDescriptors ...
|
||||
*/
|
||||
async function extractDescriptors(file = '') {
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
result = extractDescriptorsFromContent(fileContent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ConstDescriptors ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of ConstDescriptors ...
|
||||
*/
|
||||
function extractDescriptorsFromContent(content = '') {
|
||||
//
|
||||
// Prepare result ...
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(content) ||
|
||||
!content.includes(XBaseDescriptor.ExpressionKeys.Const)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract all Key Indexes ...
|
||||
const keyIndexes = XBaseDescriptor.
|
||||
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Const, content);
|
||||
|
||||
//
|
||||
// Validate Keys Exists on Content ...
|
||||
if (!XValueTools.hasChildArray(keyIndexes)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through indexes ...
|
||||
for (let index of keyIndexes) {
|
||||
//
|
||||
let startIndex = index - 1;
|
||||
let endIndex = index + XBaseDescriptor.ExpressionKeys.Const.length + 1;
|
||||
|
||||
//
|
||||
// create an empty instance of descriptor ...
|
||||
let descriptor = {
|
||||
...createDescriptor()
|
||||
}
|
||||
|
||||
//
|
||||
//#region Name and Type extractor ...
|
||||
const nameEndIndex = content.indexOf('=', index);
|
||||
identifier = content
|
||||
.substring(index + XBaseDescriptor.ExpressionKeys.Const.length, nameEndIndex)
|
||||
.trim();
|
||||
if (XValueTools.isValidArg(identifier)) {
|
||||
//
|
||||
// Check to Extract Type ...
|
||||
if (identifier.includes(':')) {
|
||||
//
|
||||
startIndex = 0;
|
||||
endIndex = identifier.indexOf(':', startIndex);
|
||||
|
||||
//
|
||||
descriptor.name = identifier
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
// Type extraction ...
|
||||
startIndex = endIndex + 1;
|
||||
descriptor.type = identifier
|
||||
.substring(startIndex)
|
||||
.trim();
|
||||
} else {
|
||||
descriptor.name = identifier;
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Extract isExported ...
|
||||
const isExported = XBaseDescriptor.checkIsExported(index, content);
|
||||
descriptor.isExported = isExported;
|
||||
if (isExported) {
|
||||
startIndex = index - XBaseDescriptor.ExpressionKeys.Export.length - 1;
|
||||
} else {
|
||||
startIndex = index;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Extract raw content ...
|
||||
identifier = content.substring(startIndex);
|
||||
startIndex = 0;
|
||||
endIndex = XValueTools.findNearestIndex(
|
||||
[
|
||||
';',
|
||||
'{',
|
||||
'[',
|
||||
'\n'
|
||||
],
|
||||
identifier,
|
||||
0 // nameEndIndex - startIndex
|
||||
);
|
||||
const nearestChar = identifier.charAt(endIndex);
|
||||
if (nearestChar === '{') {
|
||||
//
|
||||
const closedItemsIndexes = XValueTools.findClosedContent('{', '}', identifier, endIndex);
|
||||
if (!XValueTools.hasChildArray(closedItemsIndexes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
endIndex = closedItemsIndexes[0].end;
|
||||
} else if (nearestChar === '[') {
|
||||
//
|
||||
const closedItemsIndexes = XValueTools.findClosedContent('[', ']', identifier, endIndex);
|
||||
if (!XValueTools.hasChildArray(closedItemsIndexes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
endIndex = closedItemsIndexes[0].end;
|
||||
}
|
||||
|
||||
//
|
||||
identifier = identifier
|
||||
.substring(startIndex, endIndex + 1)
|
||||
.trim();
|
||||
if (XValueTools.isValidArg(identifier)) {
|
||||
descriptor.raw = identifier;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Parse Content ...
|
||||
startIndex = identifier.indexOf('=', 0);
|
||||
let contentContainer = identifier
|
||||
.substring(startIndex + 1)
|
||||
.trim()
|
||||
|
||||
//
|
||||
// Clear Content ...
|
||||
contentContainer = XBaseDescriptor
|
||||
.clearContent(contentContainer);
|
||||
|
||||
//
|
||||
const contentType = XBaseDescriptor.getContentType(contentContainer);
|
||||
const parsedContents = XBaseDescriptor.parseContent(contentContainer) || [];
|
||||
const contentDescriptor = XContentDescriptor.createDescriptor();
|
||||
|
||||
//
|
||||
contentDescriptor.type = contentType;
|
||||
contentDescriptor.childs = [
|
||||
...parsedContents
|
||||
];
|
||||
|
||||
//
|
||||
descriptor.content = {
|
||||
...contentDescriptor
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptors,
|
||||
extractDescriptorsFromContent,
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
const XKeyValueDescriptor = require('./x-key-value.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object is valid ContentDescriptor object ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
let result = false;
|
||||
result = object &&
|
||||
object.hasOwnProperty('type') &&
|
||||
object.hasOwnProperty('childs') &&
|
||||
Array.isArray(object.childs) &&
|
||||
(
|
||||
object.childs.length > 0 ?
|
||||
object.childs.every(ch => XKeyValueDescriptor.isDescriptor(ch)) :
|
||||
true
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of ContentDescriptor ...
|
||||
* @param {string} assignSymbol property assign symbol ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(
|
||||
descriptor = createDescriptor(),
|
||||
assignSymbol = ':',
|
||||
separator = ','
|
||||
) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Normalize Property Assign Symbol ...
|
||||
assignSymbol = !XValueTools.isValidArg(assignSymbol) ?
|
||||
':' :
|
||||
assignSymbol;
|
||||
|
||||
//
|
||||
const isArrayType = descriptor.type === XBaseDescriptor.ContentTypes.Array;
|
||||
const isObjectType = descriptor.type === XBaseDescriptor.ContentTypes.Object;
|
||||
|
||||
//
|
||||
result += (
|
||||
isObjectType ? '{\n' :
|
||||
isArrayType ? '[\n' :
|
||||
''
|
||||
);
|
||||
|
||||
//
|
||||
for (let i = 0; i < descriptor.childs.length; i++) {
|
||||
//
|
||||
const keyVal = descriptor.childs[i];
|
||||
const keyValExpression = XKeyValueDescriptor.toExpression(keyVal, assignSymbol);
|
||||
|
||||
//
|
||||
if (separator === ';') {
|
||||
//
|
||||
result += keyValExpression + (
|
||||
i === descriptor.childs.length - 1 ?
|
||||
separator :
|
||||
`${separator}\n`
|
||||
);
|
||||
} else {
|
||||
//
|
||||
result += keyValExpression + (
|
||||
i === descriptor.childs.length - 1 ?
|
||||
'' :
|
||||
`${separator}\n`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
result += (
|
||||
isObjectType ? '\n}' :
|
||||
isArrayType ? '\n]' :
|
||||
''
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled ContentDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value value provider object instance ...
|
||||
* @returns an instance of ContentDescriptor ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
type: XBaseDescriptor.ContentTypes.Unknown,
|
||||
childs: [
|
||||
XKeyValueDescriptor.createDescriptor()
|
||||
]
|
||||
};
|
||||
result.childs.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region type ...
|
||||
if (XBaseDescriptor.isValidContentType(value.type)) {
|
||||
result.type = value.type;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region childs ...
|
||||
if (
|
||||
XValueTools.hasChildArray(value.childs) &&
|
||||
value.childs.every(ch => XKeyValueDescriptor.isDescriptor(ch))
|
||||
) {
|
||||
result.childs = [
|
||||
...value.childs
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,307 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
const XContentDescriptor = require('./x-content.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is EnumDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result =
|
||||
object.hasOwnProperty('raw') &&
|
||||
object.hasOwnProperty('name') &&
|
||||
object.hasOwnProperty('content') &&
|
||||
object.hasOwnProperty('isExported');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled EnumDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of EnumDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
raw: '',
|
||||
name: '',
|
||||
content: {
|
||||
...XContentDescriptor.createDescriptor()
|
||||
},
|
||||
isExported: false,
|
||||
}
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region raw ...
|
||||
if (XValueTools.isValidArg(value.raw)) {
|
||||
result.raw = value.raw;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region name ...
|
||||
if (XValueTools.isValidArg(value.name)) {
|
||||
result.name = value.name;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region content ...
|
||||
if (
|
||||
value.content &&
|
||||
XContentDescriptor.isDescriptor(value.content)
|
||||
) {
|
||||
result.content = {
|
||||
...value.content
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isExported ...
|
||||
if (!!value.isExported) {
|
||||
result.isExported = value.isExported;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of EnumDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(descriptor = createDescriptor()) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result += (
|
||||
!!descriptor.isExported ?
|
||||
XBaseDescriptor.ExpressionKeys.Export + ' ' :
|
||||
''
|
||||
) +
|
||||
XBaseDescriptor.ExpressionKeys.Enum +
|
||||
' ' +
|
||||
descriptor.name +
|
||||
' ' +
|
||||
'{';
|
||||
|
||||
//
|
||||
let contentExpression = XContentDescriptor.toExpression(descriptor.content, ' =');
|
||||
if (XValueTools.isValidArg(contentExpression)) {
|
||||
//
|
||||
if (XValueTools.isSurroundedArray(contentExpression)) {
|
||||
contentExpression = XValueTools.clearArraySurround(contentExpression);
|
||||
} else if (XValueTools.isSurroundedObject(contentExpression)) {
|
||||
contentExpression = XValueTools.clearObjectSurround(contentExpression);
|
||||
}
|
||||
|
||||
//
|
||||
if (XValueTools.isValidArg(contentExpression)) {
|
||||
result += contentExpression;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
result += '}';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists EnumDescriptors ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of EnumDescriptor ...
|
||||
*/
|
||||
async function extractDescriptors(file = '') {
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
result = extractDescriptorsFromContent(fileContent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists EnumDescriptors ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of EnumDescriptor ...
|
||||
*/
|
||||
function extractDescriptorsFromContent(content = '') {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(content) ||
|
||||
!content.includes(XBaseDescriptor.ExpressionKeys.Enum)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract all key Indexes ...
|
||||
const keyIndexes = XBaseDescriptor.
|
||||
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Enum, content);
|
||||
|
||||
//
|
||||
// Validate them ...
|
||||
if (!XValueTools.hasChildArray(keyIndexes)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through indexes ...
|
||||
for (const index of keyIndexes) {
|
||||
//
|
||||
let startIndex = index - 1;
|
||||
let endIndex = index + XBaseDescriptor.ExpressionKeys.Enum.length + 1;
|
||||
|
||||
//
|
||||
// create an empty instance of descriptor ...
|
||||
let descriptor = {
|
||||
...createDescriptor()
|
||||
}
|
||||
|
||||
//
|
||||
//#region Name extractor ...
|
||||
const nameEndIndex = content.indexOf('{', index);
|
||||
identifier = content
|
||||
.substring(index + XBaseDescriptor.ExpressionKeys.Enum.length, nameEndIndex)
|
||||
.trim();
|
||||
if (XValueTools.isValidArg(identifier)) {
|
||||
descriptor.name = identifier;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Extract isExported ...
|
||||
const isExported = XBaseDescriptor.checkIsExported(index, content);
|
||||
descriptor.isExported = isExported;
|
||||
if (isExported) {
|
||||
startIndex = index - XBaseDescriptor.ExpressionKeys.Export.length - 1;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Extract raw content ...
|
||||
identifier = content.substring(startIndex);
|
||||
let closedContenstIndexes = XValueTools.findClosedContent('{', '}', identifier);
|
||||
if (!XValueTools.hasChildArray(closedContenstIndexes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
startIndex = 0;
|
||||
endIndex = closedContenstIndexes[0].end;
|
||||
if (endIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
const raw = identifier.substring(startIndex, endIndex + 1);
|
||||
if (!XValueTools.isValidArg(raw)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
descriptor.raw = raw;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Parse Enum Content ...
|
||||
startIndex = closedContenstIndexes[0].start;
|
||||
endIndex = closedContenstIndexes[0].end + 1;
|
||||
let contentContainer = identifier.substring(startIndex, endIndex);
|
||||
contentContainer = XBaseDescriptor.clearContent(contentContainer);
|
||||
|
||||
//
|
||||
const contentType = XBaseDescriptor.getContentType(contentContainer);
|
||||
const parsedContents = XBaseDescriptor.parseContent(contentContainer);
|
||||
const contentDescriptor = XContentDescriptor.createDescriptor();
|
||||
|
||||
//
|
||||
contentDescriptor.type = contentType;
|
||||
contentDescriptor.childs = [
|
||||
...parsedContents
|
||||
];
|
||||
|
||||
//
|
||||
descriptor.content = {
|
||||
...contentDescriptor
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Moduile Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptors,
|
||||
extractDescriptorsFromContent,
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is ExportDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result = Array.isArray(object.objects) &&
|
||||
object.hasOwnProperty('raw') &&
|
||||
object.hasOwnProperty('type') &&
|
||||
object.hasOwnProperty('module') &&
|
||||
object.hasOwnProperty('objects');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled ExportDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of ExportDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
raw: '',
|
||||
type: '',
|
||||
module: '',
|
||||
objects: ['']
|
||||
}
|
||||
result.objects.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region raw ...
|
||||
if (XValueTools.isValidArg(value.raw)) {
|
||||
result.raw = value.raw;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region type ...
|
||||
if (
|
||||
XValueTools.isValidArg(value.type) ||
|
||||
XBaseDescriptor.isValidContentType(value.type)
|
||||
) {
|
||||
result.type = value.type;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region module ..
|
||||
if (XValueTools.isValidArg(value.module)) {
|
||||
result.module = value.module;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region objects ...
|
||||
if (XValueTools.hasChildArray(value.objects)) {
|
||||
result.objects = [
|
||||
...value.objects
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of ExportDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(descriptor = createDescriptor()) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result += XBaseDescriptor.ExpressionKeys.Export +
|
||||
' ';
|
||||
|
||||
//
|
||||
//#region objects ...
|
||||
//
|
||||
if (descriptor.type === XBaseDescriptor.ContentTypes.Object) {
|
||||
//
|
||||
let objectsIdentifier = descriptor.objects.join(', ');
|
||||
objectsIdentifier = `{ ${objectsIdentifier} }`;
|
||||
|
||||
//
|
||||
result += objectsIdentifier;
|
||||
} else {
|
||||
result += descriptor.objects[0];
|
||||
}
|
||||
|
||||
//
|
||||
result += ' ';
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region module ...
|
||||
result += XBaseDescriptor.ExpressionKeys.From +
|
||||
' ' +
|
||||
XValueTools.surroundBy('\'', descriptor.module);
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result += ';'
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ExportDescriptor ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of ExportDescriptor ...
|
||||
*/
|
||||
async function extractDescriptors(file = '') {
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
result = extractDescriptorsFromContent(fileContent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ExportDescriptor ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of ExportDescriptor ...
|
||||
*/
|
||||
function extractDescriptorsFromContent(content = '') {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(content) ||
|
||||
!content.includes(XBaseDescriptor.ExpressionKeys.Export)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract all key Indexes ...
|
||||
const keyIndexes = XBaseDescriptor.
|
||||
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Export, content)
|
||||
.filter(i => {
|
||||
//
|
||||
// Exports ...
|
||||
let startIndex = i;
|
||||
let key = XBaseDescriptor.ExpressionKeys.Exports;
|
||||
let endIndex = startIndex + key.length;
|
||||
let subStr = content.substring(startIndex, endIndex);
|
||||
if (subStr === key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Const ...
|
||||
startIndex = i + XBaseDescriptor.ExpressionKeys.Export.length + 1;
|
||||
key = XBaseDescriptor.ExpressionKeys.Const;
|
||||
endIndex = startIndex + key.length;
|
||||
subStr = content.substring(startIndex, endIndex);
|
||||
if (subStr === key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Enum ...
|
||||
key = XBaseDescriptor.ExpressionKeys.Enum;
|
||||
endIndex = startIndex + key.length;
|
||||
subStr = content.substring(startIndex, endIndex);
|
||||
if (subStr === key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Type ...
|
||||
key = XBaseDescriptor.ExpressionKeys.Type;
|
||||
endIndex = startIndex + key.length;
|
||||
subStr = content.substring(startIndex, endIndex);
|
||||
if (subStr === key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Class ...
|
||||
key = XBaseDescriptor.ExpressionKeys.Class;
|
||||
endIndex = startIndex + key.length;
|
||||
subStr = content.substring(startIndex, endIndex);
|
||||
if (subStr === key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Interface ...
|
||||
key = XBaseDescriptor.ExpressionKeys.Interface;
|
||||
endIndex = startIndex + key.length;
|
||||
subStr = content.substring(startIndex, endIndex);
|
||||
if (subStr === key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
return true;
|
||||
});
|
||||
|
||||
//
|
||||
// Validate them ...
|
||||
if (!XValueTools.hasChildArray(keyIndexes)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through indexes ...
|
||||
for (const index of keyIndexes) {
|
||||
//
|
||||
// create an empty instance of descriptor ...
|
||||
let descriptor = {
|
||||
...createDescriptor()
|
||||
}
|
||||
|
||||
//
|
||||
let startIndex = index;
|
||||
let endIndex = XValueTools.findNearestIndex(
|
||||
[
|
||||
';',
|
||||
'\n'
|
||||
],
|
||||
content,
|
||||
startIndex
|
||||
);
|
||||
const nearestChar = content.charAt(endIndex);
|
||||
if (nearestChar === ';') {
|
||||
endIndex++;
|
||||
}
|
||||
|
||||
//
|
||||
let identifier = content
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
// Check Identifier must includes FROM ...
|
||||
if (!identifier.includes(XBaseDescriptor.ExpressionKeys.From)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
//#region raw ...
|
||||
const raw = identifier;
|
||||
descriptor.raw = raw;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
const fromIndex = identifier.indexOf(XBaseDescriptor.ExpressionKeys.From);
|
||||
|
||||
//
|
||||
//#region extracts Objects ...
|
||||
startIndex = XBaseDescriptor.ExpressionKeys.Import.length;
|
||||
endIndex = fromIndex;
|
||||
identifier = identifier
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
// Clear Unused Content ...
|
||||
identifier = XBaseDescriptor.clearContent(identifier);
|
||||
|
||||
//
|
||||
// Clear Also \n ...
|
||||
identifier = XValueTools.clearContent('\n', identifier);
|
||||
|
||||
//
|
||||
if (XValueTools.isSurroundedObject(identifier)) {
|
||||
//
|
||||
// Clear Object Surround ...
|
||||
identifier = XValueTools.clearObjectSurround(identifier);
|
||||
|
||||
//
|
||||
// Extract Imported Objects ...
|
||||
let importedObjects = identifier
|
||||
.split(',')
|
||||
.map(o => o.trim())
|
||||
.filter(o => XValueTools.isValidArg(o));
|
||||
|
||||
//
|
||||
descriptor.type = XBaseDescriptor.ContentTypes.Object;
|
||||
descriptor.objects = [
|
||||
...importedObjects
|
||||
];
|
||||
} else {
|
||||
//
|
||||
descriptor.type = XBaseDescriptor.ContentTypes.String;
|
||||
descriptor.objects.push(identifier)
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Module ...
|
||||
startIndex = fromIndex + XBaseDescriptor.ExpressionKeys.From.length;
|
||||
identifier = raw
|
||||
.substring(startIndex)
|
||||
.trim();
|
||||
identifier = XValueTools.findClosedStrings(identifier)[0].content;
|
||||
if (XValueTools.isSurroundedString(identifier)) {
|
||||
//
|
||||
const surroundSymbol = identifier.charAt(0);
|
||||
identifier = XValueTools.clearSurround(surroundSymbol, identifier);
|
||||
}
|
||||
|
||||
//
|
||||
descriptor.module = identifier;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
//#region Custom Actions ...
|
||||
function update(
|
||||
descriptors,
|
||||
addOrUpdates
|
||||
) {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = [createDescriptor()];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
//#region Validate Args ...
|
||||
//
|
||||
// Validate Descriptors ...
|
||||
if (XValueTools.hasChildArray(descriptors)) {
|
||||
//
|
||||
// Validate All Objects is Descriptor ...
|
||||
const isAllIsImport = descriptors.every(d => isDescriptor(d));
|
||||
if (!isAllIsImport) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = [
|
||||
...descriptors
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Validate addOrUpdates ...
|
||||
if (XValueTools.hasChildArray(addOrUpdates)) {
|
||||
//
|
||||
// Validate All Objects is Descriptor ...
|
||||
const isAllIsImport = addOrUpdates.every(d => isDescriptor(d));
|
||||
if (!isAllIsImport) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
for (const desc of addOrUpdates) {
|
||||
//
|
||||
// Find same Module if exists ...
|
||||
//
|
||||
let descriptor = createDescriptor(desc);
|
||||
|
||||
//
|
||||
let existsModuleIndex = result.findIndex(d => descriptor.module === d.module);
|
||||
if (existsModuleIndex >= 0) {
|
||||
//
|
||||
descriptor = result[existsModuleIndex];
|
||||
let mustAddObjects = desc.objects.filter(o => o.includes('*') ||
|
||||
!descriptor.objects.includes(o));
|
||||
if (XValueTools.hasChildArray(mustAddObjects)) {
|
||||
descriptor.objects = [
|
||||
...descriptor.objects,
|
||||
...mustAddObjects
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
result[existsModuleIndex] = {
|
||||
...descriptor
|
||||
};
|
||||
} else {
|
||||
//
|
||||
let mustAddObjects = descriptor.objects.filter(o => o.includes('*') ||
|
||||
result
|
||||
.map(d => d.objects)
|
||||
.every(objects => !objects.includes(o))
|
||||
);
|
||||
|
||||
//
|
||||
descriptor.objects = [
|
||||
...mustAddObjects
|
||||
];
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Moduile Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptors,
|
||||
extractDescriptorsFromContent,
|
||||
|
||||
//
|
||||
update,
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
const XEnumDescriptor = require('./x-enum.descriptor');
|
||||
const XTypeDescriptor = require('./x-type.descriptor');
|
||||
const XClassDescriptor = require('./x-class.descriptor');
|
||||
const XConstDescriptor = require('./x-const.descriptor');
|
||||
const XImportDescriptor = require('./x-import.descriptor');
|
||||
const XExportDescriptor = require('./x-export.descriptor');
|
||||
const XInterfaceDescriptor = require('./x-interface.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is XFileDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result =
|
||||
Array.isArray(object.types) &&
|
||||
object.hasOwnProperty('types') &&
|
||||
//
|
||||
Array.isArray(object.enums) &&
|
||||
object.hasOwnProperty('enums') &&
|
||||
//
|
||||
Array.isArray(object.consts) &&
|
||||
object.hasOwnProperty('consts') &&
|
||||
//
|
||||
Array.isArray(object.classes) &&
|
||||
object.hasOwnProperty('classes') &&
|
||||
//
|
||||
Array.isArray(object.imports) &&
|
||||
object.hasOwnProperty('imports') &&
|
||||
//
|
||||
Array.isArray(object.exports) &&
|
||||
object.hasOwnProperty('exports') &&
|
||||
//
|
||||
Array.isArray(object.interfaces) &&
|
||||
object.hasOwnProperty('interfaces');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled XFileDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of XFileDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
types: [XTypeDescriptor.createDescriptor()],
|
||||
enums: [XEnumDescriptor.createDescriptor()],
|
||||
consts: [XConstDescriptor.createDescriptor()],
|
||||
classes: [XClassDescriptor.createDescriptor()],
|
||||
imports: [XImportDescriptor.createDescriptor()],
|
||||
exports: [XExportDescriptor.createDescriptor()],
|
||||
interfaces: [XInterfaceDescriptor.createDescriptor()],
|
||||
};
|
||||
|
||||
//
|
||||
result.types.pop();
|
||||
result.enums.pop();
|
||||
result.consts.pop();
|
||||
result.classes.pop();
|
||||
result.imports.pop();
|
||||
result.exports.pop();
|
||||
result.interfaces.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region types ...
|
||||
if (XValueTools.hasChildArray(value.types)) {
|
||||
result.types = [
|
||||
...value.types
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region enums ...
|
||||
if (XValueTools.hasChildArray(value.enums)) {
|
||||
result.enums = [
|
||||
...value.enums
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region consts ...
|
||||
if (XValueTools.hasChildArray(value.consts)) {
|
||||
result.consts = [
|
||||
...value.consts
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region classes ...
|
||||
if (XValueTools.hasChildArray(value.classes)) {
|
||||
result.classes = [
|
||||
...value.classes
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region imports ...
|
||||
if (XValueTools.hasChildArray(value.imports)) {
|
||||
result.imports = [
|
||||
...value.imports
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region exports ...
|
||||
if (XValueTools.hasChildArray(value.exports)) {
|
||||
result.exports = [
|
||||
...value.exports
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region interfaces ...
|
||||
if (XValueTools.hasChildArray(value.interfaces)) {
|
||||
result.interfaces = [
|
||||
...value.interfaces
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of XFileDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(descriptor = createDescriptor()) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
//#region Imports ...
|
||||
if (XValueTools.hasChildArray(descriptor.imports)) {
|
||||
//
|
||||
const expression = descriptor.imports
|
||||
.map(d => XImportDescriptor
|
||||
.toExpression(d)
|
||||
).join('\n');
|
||||
|
||||
//
|
||||
result += expression + '\n\n';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Enums ...
|
||||
if (XValueTools.hasChildArray(descriptor.enums)) {
|
||||
//
|
||||
const expression = descriptor.enums
|
||||
.map(d => XEnumDescriptor
|
||||
.toExpression(d)
|
||||
).join('\n');
|
||||
|
||||
//
|
||||
result += expression + '\n\n';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Types ...
|
||||
if (XValueTools.hasChildArray(descriptor.types)) {
|
||||
//
|
||||
const expression = descriptor.types
|
||||
.map(d => XTypeDescriptor
|
||||
.toExpression(d)
|
||||
).join('\n');
|
||||
|
||||
//
|
||||
result += expression + '\n\n';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Interfaces ...
|
||||
if (XValueTools.hasChildArray(descriptor.interfaces)) {
|
||||
//
|
||||
const expression = descriptor.interfaces
|
||||
.map(d => XInterfaceDescriptor
|
||||
.toExpression(d)
|
||||
).join('\n');
|
||||
|
||||
//
|
||||
result += expression + '\n\n';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Consts ...
|
||||
if (XValueTools.hasChildArray(descriptor.consts)) {
|
||||
//
|
||||
const expression = descriptor.consts
|
||||
.map(d => XConstDescriptor
|
||||
.toExpression(d)
|
||||
).join('\n');
|
||||
|
||||
//
|
||||
result += expression + '\n\n';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Classes ...
|
||||
if (XValueTools.hasChildArray(descriptor.classes)) {
|
||||
//
|
||||
const expression = descriptor.classes
|
||||
.map(d => XClassDescriptor
|
||||
.toExpression(d)
|
||||
).join('\n');
|
||||
|
||||
//
|
||||
result += expression + '\n\n';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Exports ...
|
||||
if (XValueTools.hasChildArray(descriptor.exports)) {
|
||||
//
|
||||
const expression = descriptor.exports
|
||||
.map(d => XExportDescriptor
|
||||
.toExpression(d)
|
||||
).join('\n');
|
||||
|
||||
//
|
||||
result += expression + '\n\n';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
if (XValueTools.endsWidth('\n', result)) {
|
||||
result = result.substring(0, result.length - 1);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists XFileDescriptors ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of XFileDescriptors ...
|
||||
*/
|
||||
async function extractDescriptor(file = '') {
|
||||
//
|
||||
let result = createDescriptor();
|
||||
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//
|
||||
result = extractDescriptorFromContent(fileContent);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists XFileDescriptors ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of XFileDescriptors ...
|
||||
*/
|
||||
function extractDescriptorFromContent(content = '') {
|
||||
//
|
||||
// Prepare result ...
|
||||
let result = createDescriptor();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (!XValueTools.isValidArg(content)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//
|
||||
const types = XTypeDescriptor.extractDescriptorsFromContent(content);
|
||||
const enums = XEnumDescriptor.extractDescriptorsFromContent(content);
|
||||
const consts = XConstDescriptor.extractDescriptorsFromContent(content);
|
||||
const classes = XClassDescriptor.extractDescriptorsFromContent(content);
|
||||
const exports = XExportDescriptor.extractDescriptorsFromContent(content);
|
||||
const imports = XImportDescriptor.extractDescriptorsFromContent(content);
|
||||
const interfaces = XInterfaceDescriptor.extractDescriptorsFromContent(content);
|
||||
|
||||
//
|
||||
result = {
|
||||
types,
|
||||
enums,
|
||||
consts,
|
||||
imports,
|
||||
exports,
|
||||
classes,
|
||||
interfaces,
|
||||
};
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptor,
|
||||
extractDescriptorFromContent,
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is ImportDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result = Array.isArray(object.objects) &&
|
||||
object.hasOwnProperty('raw') &&
|
||||
object.hasOwnProperty('type') &&
|
||||
object.hasOwnProperty('module') &&
|
||||
object.hasOwnProperty('objects');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled ImportDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of ImportDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
raw: '',
|
||||
type: '',
|
||||
module: '',
|
||||
objects: ['']
|
||||
}
|
||||
result.objects.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region raw ...
|
||||
if (XValueTools.isValidArg(value.raw)) {
|
||||
result.raw = value.raw;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region type ...
|
||||
if (
|
||||
XValueTools.isValidArg(value.type) ||
|
||||
XBaseDescriptor.isValidContentType(value.type)
|
||||
) {
|
||||
result.type = value.type;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region module ..
|
||||
if (XValueTools.isValidArg(value.module)) {
|
||||
result.module = value.module;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region objects ...
|
||||
if (XValueTools.hasChildArray(value.objects)) {
|
||||
result.objects = [
|
||||
...value.objects
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of ImportDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(descriptor = createDescriptor()) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result += XBaseDescriptor.ExpressionKeys.Import +
|
||||
' ';
|
||||
|
||||
//
|
||||
//#region objects ...
|
||||
//
|
||||
if (descriptor.type === XBaseDescriptor.ContentTypes.Object) {
|
||||
//
|
||||
let objectsIdentifier = descriptor.objects.join(', ');
|
||||
objectsIdentifier = `{ ${objectsIdentifier} }`;
|
||||
|
||||
//
|
||||
result += objectsIdentifier;
|
||||
} else {
|
||||
result += descriptor.objects[0];
|
||||
}
|
||||
|
||||
//
|
||||
result += ' ';
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region module ...
|
||||
result += XBaseDescriptor.ExpressionKeys.From +
|
||||
' ' +
|
||||
XValueTools.surroundBy('\'', descriptor.module);
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result += ';'
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ImportDescriptor ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of ImportDescriptor ...
|
||||
*/
|
||||
async function extractDescriptors(file = '') {
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
result = extractDescriptorsFromContent(fileContent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists ImportDescriptor ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of ImportDescriptor ...
|
||||
*/
|
||||
function extractDescriptorsFromContent(content = '') {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(content) ||
|
||||
!content.includes(XBaseDescriptor.ExpressionKeys.Import)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract all key Indexes ...
|
||||
const keyIndexes = XBaseDescriptor.
|
||||
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Import, content);
|
||||
|
||||
//
|
||||
// Validate them ...
|
||||
if (!XValueTools.hasChildArray(keyIndexes)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through indexes ...
|
||||
for (const index of keyIndexes) {
|
||||
//
|
||||
// create an empty instance of descriptor ...
|
||||
let descriptor = {
|
||||
...createDescriptor()
|
||||
}
|
||||
|
||||
//
|
||||
let startIndex = index;
|
||||
let endIndex = XValueTools.findNearestIndex(
|
||||
[
|
||||
';',
|
||||
'\n'
|
||||
],
|
||||
content,
|
||||
startIndex
|
||||
);
|
||||
const nearestChar = content.charAt(endIndex);
|
||||
if (nearestChar === ';') {
|
||||
endIndex++;
|
||||
}
|
||||
|
||||
//
|
||||
let identifier = content
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
// Check Identifier must includes FROM ...
|
||||
if (!identifier.includes(XBaseDescriptor.ExpressionKeys.From)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
//#region raw ...
|
||||
const raw = identifier;
|
||||
descriptor.raw = raw;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
const fromIndex = identifier.indexOf(XBaseDescriptor.ExpressionKeys.From);
|
||||
|
||||
//
|
||||
//#region extracts Objects ...
|
||||
startIndex = XBaseDescriptor.ExpressionKeys.Import.length;
|
||||
endIndex = fromIndex;
|
||||
identifier = identifier
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
// Clear Unused Content ...
|
||||
identifier = XBaseDescriptor.clearContent(identifier);
|
||||
|
||||
//
|
||||
// Clear Also \n ...
|
||||
identifier = XValueTools.clearContent('\n', identifier);
|
||||
|
||||
//
|
||||
if (XValueTools.isSurroundedObject(identifier)) {
|
||||
//
|
||||
// Type ...
|
||||
descriptor.type = XBaseDescriptor.ContentTypes.Object;
|
||||
|
||||
//
|
||||
// Clear Object Surround ...
|
||||
identifier = XValueTools.clearObjectSurround(identifier);
|
||||
|
||||
//
|
||||
// Extract Imported Objects ...
|
||||
let importedObjects = identifier
|
||||
.split(',')
|
||||
.map(o => o.trim())
|
||||
.filter(o => XValueTools.isValidArg(o));
|
||||
|
||||
//
|
||||
descriptor.objects = [
|
||||
...importedObjects
|
||||
];
|
||||
} else {
|
||||
//
|
||||
descriptor.type = XBaseDescriptor.ContentTypes.String;
|
||||
descriptor.objects.push(identifier)
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Module ...
|
||||
startIndex = fromIndex + XBaseDescriptor.ExpressionKeys.From.length;
|
||||
identifier = raw
|
||||
.substring(startIndex)
|
||||
.trim();
|
||||
identifier = XValueTools.findClosedStrings(identifier)[0].content;
|
||||
if (XValueTools.isSurroundedString(identifier)) {
|
||||
//
|
||||
const surroundSymbol = identifier.charAt(0);
|
||||
identifier = XValueTools.clearSurround(surroundSymbol, identifier);
|
||||
}
|
||||
|
||||
//
|
||||
descriptor.module = identifier;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
//#region Custom Actions ...
|
||||
function update(
|
||||
descriptors,
|
||||
addOrUpdates
|
||||
) {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = [createDescriptor()];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
//#region Validate Args ...
|
||||
//
|
||||
// Validate Descriptors ...
|
||||
if (XValueTools.hasChildArray(descriptors)) {
|
||||
//
|
||||
// Validate All Objects is Descriptor ...
|
||||
const isAllIsImport = descriptors.every(d => isDescriptor(d));
|
||||
if (!isAllIsImport) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = [
|
||||
...descriptors
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Validate addOrUpdates ...
|
||||
if (XValueTools.hasChildArray(addOrUpdates)) {
|
||||
//
|
||||
// Validate All Objects is Descriptor ...
|
||||
const isAllIsImport = addOrUpdates.every(d => isDescriptor(d));
|
||||
if (!isAllIsImport) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
for (const desc of addOrUpdates) {
|
||||
//
|
||||
// Find same Module if exists ...
|
||||
//
|
||||
let descriptor = createDescriptor(desc);
|
||||
|
||||
//
|
||||
let existsModuleIndex = result.findIndex(d => descriptor.module === d.module);
|
||||
if (existsModuleIndex >= 0) {
|
||||
//
|
||||
descriptor = result[existsModuleIndex];
|
||||
let mustAddObjects = desc.objects.filter(o => o.includes('*') ||
|
||||
!descriptor.objects.includes(o));
|
||||
if (XValueTools.hasChildArray(mustAddObjects)) {
|
||||
descriptor.objects = [
|
||||
...descriptor.objects,
|
||||
...mustAddObjects
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
result[existsModuleIndex] = {
|
||||
...descriptor
|
||||
};
|
||||
} else {
|
||||
//
|
||||
let mustAddObjects = descriptor.objects
|
||||
.filter(o => o.includes('*') ||
|
||||
result
|
||||
.map(d => d.objects)
|
||||
.every(objects => !objects.includes(o))
|
||||
);
|
||||
|
||||
//
|
||||
descriptor.objects = [
|
||||
...mustAddObjects
|
||||
];
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Moduile Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptors,
|
||||
extractDescriptorsFromContent,
|
||||
//
|
||||
update,
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
const XContentDescriptor = require('./x-content.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is InterfaceDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result =
|
||||
object.hasOwnProperty('raw') &&
|
||||
object.hasOwnProperty('name') &&
|
||||
Array.isArray(object.extends) &&
|
||||
object.hasOwnProperty('extends') &&
|
||||
object.hasOwnProperty('isExtended') &&
|
||||
object.hasOwnProperty('isExported');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled InterfaceDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of InterfaceDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
raw: '',
|
||||
name: '',
|
||||
extends: [''],
|
||||
isExtended: false,
|
||||
isExported: false,
|
||||
properties: {
|
||||
...XContentDescriptor.createDescriptor()
|
||||
},
|
||||
};
|
||||
result.extends.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region raw ...
|
||||
if (XValueTools.isValidArg(value.raw)) {
|
||||
result.raw = value.raw;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region name ...
|
||||
if (XValueTools.isValidArg(value.name)) {
|
||||
result.name = value.name;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isExported ...
|
||||
if (!!value.isExported) {
|
||||
result.isExported = value.isExported;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isExtended ...
|
||||
if (!!value.isExtended) {
|
||||
result.isExtended = value.isExtended;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region extends ...
|
||||
if (XValueTools.hasChildArray(value.extends)) {
|
||||
result.extends = [
|
||||
...value.extends
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region properties ...
|
||||
if (
|
||||
value.properties &&
|
||||
XContentDescriptor.isDescriptor(value.properties)
|
||||
) {
|
||||
result.properties = {
|
||||
...value.properties
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of InterfaceDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(descriptor = createDescriptor()) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result += (
|
||||
!!descriptor.isExported ?
|
||||
XBaseDescriptor.ExpressionKeys.Export + ' ' :
|
||||
''
|
||||
) +
|
||||
XBaseDescriptor.ExpressionKeys.Interface +
|
||||
' ' +
|
||||
descriptor.name +
|
||||
' ' +
|
||||
(
|
||||
!!descriptor.isExtended &&
|
||||
XValueTools.hasChildArray(descriptor.extends) ?
|
||||
XBaseDescriptor.ExpressionKeys.Extends +
|
||||
' ' +
|
||||
descriptor.extends.join(', ') +
|
||||
' ' :
|
||||
''
|
||||
);
|
||||
|
||||
//
|
||||
let contentExpression = XContentDescriptor.toExpression(descriptor.properties, ':', ';');
|
||||
if (XValueTools.isValidArg(contentExpression)) {
|
||||
result += contentExpression;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists InterfaceDescriptors ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of InterfaceDescriptors ...
|
||||
*/
|
||||
async function extractDescriptors(file = '') {
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
result = extractDescriptorsFromContent(fileContent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists InterfaceDescriptors ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of InterfaceDescriptors ...
|
||||
*/
|
||||
function extractDescriptorsFromContent(content = '') {
|
||||
//
|
||||
// Prepare result ...
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(content) ||
|
||||
!content.includes(XBaseDescriptor.ExpressionKeys.Interface)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract all Key Indexes ...
|
||||
const keyIndexes = XBaseDescriptor.
|
||||
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Interface, content);
|
||||
|
||||
//
|
||||
// Validate Keys Exists on Content ...
|
||||
if (!XValueTools.hasChildArray(keyIndexes)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through indexes ...
|
||||
for (let index of keyIndexes) {
|
||||
//
|
||||
let startIndex = index - 1;
|
||||
let endIndex = index + XBaseDescriptor.ExpressionKeys.Interface.length + 1;
|
||||
|
||||
//
|
||||
// create an empty instance of descriptor ...
|
||||
let descriptor = {
|
||||
...createDescriptor()
|
||||
}
|
||||
|
||||
//
|
||||
//#region Extract isExported ...
|
||||
const isExported = XBaseDescriptor.checkIsExported(index, content);
|
||||
descriptor.isExported = isExported;
|
||||
if (isExported) {
|
||||
startIndex = index - XBaseDescriptor.ExpressionKeys.Export.length - 1;
|
||||
} else {
|
||||
startIndex = index;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Closed Item ...
|
||||
let closedContents = XValueTools.findClosedContent('{', '}', content, index);
|
||||
if (!XValueTools.hasChildArray(closedContents)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
let interfaceContentIndexer = closedContents[0];
|
||||
endIndex = interfaceContentIndexer.start - 1;
|
||||
|
||||
//
|
||||
identifier = content
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
//#region extract Name, Extends ...
|
||||
let name = '';
|
||||
let nameCandidate = identifier
|
||||
.replace(XBaseDescriptor.ExpressionKeys.Export, '')
|
||||
.replace(XBaseDescriptor.ExpressionKeys.Interface, '')
|
||||
.trim();
|
||||
let extendsIdentifiers = nameCandidate;
|
||||
if (nameCandidate.includes(XBaseDescriptor.ExpressionKeys.Extends)) {
|
||||
//
|
||||
// Name ...
|
||||
let nameEndIndex = nameCandidate.indexOf(XBaseDescriptor.ExpressionKeys.Extends);
|
||||
nameCandidate = nameCandidate
|
||||
.substring(0, nameEndIndex)
|
||||
.trim();
|
||||
|
||||
//
|
||||
//isExtended ...
|
||||
descriptor.isExtended = true;
|
||||
extendsIdentifiers = extendsIdentifiers
|
||||
.substring(nameEndIndex + XBaseDescriptor.ExpressionKeys.Extends.length)
|
||||
.trim();
|
||||
|
||||
//
|
||||
if (
|
||||
!XValueTools.isValidArg(nameCandidate) ||
|
||||
!XValueTools.isValidArg(extendsIdentifiers)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Extends ...
|
||||
descriptor.extends = [
|
||||
...extendsIdentifiers
|
||||
.split(',')
|
||||
.map(e => e.trim())
|
||||
.filter(e => XValueTools.isValidArg(e))
|
||||
];
|
||||
|
||||
//
|
||||
name = nameCandidate;
|
||||
} else {
|
||||
name = nameCandidate;
|
||||
}
|
||||
|
||||
//
|
||||
if (!XValueTools.isValidArg(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
descriptor.name = name;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region extract Content ...
|
||||
let contentContainer = interfaceContentIndexer.content;
|
||||
|
||||
//
|
||||
// Clear Content ...
|
||||
contentContainer = XBaseDescriptor
|
||||
.clearContent(contentContainer);
|
||||
|
||||
//
|
||||
const contentType = XBaseDescriptor.getContentType(contentContainer);
|
||||
const parsedContents = XBaseDescriptor.parseContent(
|
||||
contentContainer,
|
||||
true
|
||||
);
|
||||
const contentDescriptor = XContentDescriptor.createDescriptor();
|
||||
|
||||
//
|
||||
contentDescriptor.type = contentType;
|
||||
contentDescriptor.childs = [
|
||||
...parsedContents
|
||||
];
|
||||
|
||||
//
|
||||
descriptor.properties = {
|
||||
...contentDescriptor
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Extract raw content ...
|
||||
//
|
||||
endIndex = interfaceContentIndexer.end + 1;
|
||||
identifier = content
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
if (!XValueTools.isValidArg(identifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
descriptor.raw = identifier;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptors,
|
||||
extractDescriptorsFromContent,
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object is valid key/value object ...
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
let result = false;
|
||||
result = object &&
|
||||
object.hasOwnProperty('key') &&
|
||||
object.hasOwnProperty('type') &&
|
||||
object.hasOwnProperty('value');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled KeyValueProvider object instance ...
|
||||
*
|
||||
* @param {any} value value provider object instance ...
|
||||
* @returns an instance of KeyValueDescriptor ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
const result = {
|
||||
key: '',
|
||||
value: undefined,
|
||||
type: XBaseDescriptor.ContentTypes.Unknown,
|
||||
};
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region key ...
|
||||
if (XValueTools.isValidArg(value.key)) {
|
||||
result.key = value.key;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region type ...
|
||||
if (
|
||||
XValueTools.isValidArg(value.type) &&
|
||||
XBaseDescriptor.isValidContentType(value.type)
|
||||
) {
|
||||
result.type = value.type;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region value ...
|
||||
if (value.value) {
|
||||
result.value = value.value;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of KeyValueDescriptor ...
|
||||
* @param {string} assignSymbol property assign symbol ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(
|
||||
descriptor = createDescriptor(),
|
||||
assignSymbol = ''
|
||||
) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Normalize Assign Symbol ...
|
||||
assignSymbol = !XValueTools.isValidArg(assignSymbol) ?
|
||||
'' :
|
||||
assignSymbol;
|
||||
|
||||
//
|
||||
// Handle Key ...
|
||||
if (descriptor.key !== XBaseDescriptor.ExpressionKeys.IGNORED_KEY) {
|
||||
result += descriptor.key + assignSymbol + ' ';
|
||||
}
|
||||
|
||||
//
|
||||
// Handle Value ...
|
||||
const valueExpression = XBaseDescriptor.toExpression(descriptor);
|
||||
result += valueExpression;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
const XConstDescriptor = require('./x-const.descriptor');
|
||||
const XContentDescriptor = require('./x-content.descriptor');
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
/**
|
||||
* all possible usage of localeResources ...
|
||||
*/
|
||||
const LocalizationResourceIdentifiers = {
|
||||
ResourceIDs: 'ResourceIDs.',
|
||||
XResourceIDs: 'XResourceIDs.',
|
||||
XAppResourceIDs: 'AppResourceIDs.',
|
||||
ThisResourceIDs: 'this.ResourceIDs.',
|
||||
ThisAppResourceIDs: 'this.AppResourceIDs.',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region ResourceIDsDescriptor ...
|
||||
/**
|
||||
* check an object instance is ResourceIDsDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isResourceIDsDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result =
|
||||
object.hasOwnProperty('resourceIds') &&
|
||||
object.hasOwnProperty('appResourceIds') &&
|
||||
Array.isArray(object.resourceIds) &&
|
||||
Array.isArray(object.appResourceIds);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled ResourceIDsDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of ResourceIDsDescriptor object ...
|
||||
*/
|
||||
function createResourceIDsDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
resourceIds: [''],
|
||||
appResourceIds: ['']
|
||||
}
|
||||
result.resourceIds.pop();
|
||||
result.appResourceIds.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region ResourceIDs ...
|
||||
if (XValueTools.hasChildArray(value.resourceIds)) {
|
||||
result.resourceIds = [
|
||||
...value.resourceIds
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region appResourceIds ...
|
||||
if (XValueTools.hasChildArray(value.appResourceIds)) {
|
||||
result.appResourceIds = [
|
||||
...value.appResourceIds
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract exists used ResourceIds form files ...
|
||||
*
|
||||
* @param {string|string[]} files a file(s) path ...
|
||||
* @returns an instance of ResourceIDsDescriptor ...
|
||||
*/
|
||||
async function extractResourceIDsDescriptor(files) {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = createResourceIDsDescriptor();
|
||||
|
||||
//
|
||||
// Normalize Files ...
|
||||
const normalFiles = XValueTools.toNormalArray(files);
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.hasChildArray(normalFiles) ||
|
||||
!normalFiles.every(file => XFileTools.isFileExists(file))
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
const readFileContentTasks = normalFiles.map(file => XFileTools.readFile(file));
|
||||
const fileContents = await Promise.all(readFileContentTasks);
|
||||
if (!XValueTools.hasChildArray(fileContents)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = extractResourceIDsDescriptorFromContent(fileContents);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract exists ResourceIDsDescriptor from file contents ...
|
||||
*
|
||||
* @param {string|string[]} contents a file(s) content(s) ...
|
||||
* @returns an instance of ResourceIDsDescriptor ...
|
||||
*/
|
||||
function extractResourceIDsDescriptorFromContent(contents) {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = createResourceIDsDescriptor();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (!contents) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Normalize Contents ...
|
||||
const normalContents = XValueTools
|
||||
.toNormalArray(contents)
|
||||
.map(c => c.trim())
|
||||
.filter(c => XValueTools.isValidArg(c));
|
||||
if (!XValueTools.hasChildArray(normalContents)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through all normal contents and extract result ...
|
||||
for (const content of normalContents) {
|
||||
//
|
||||
// Find all indexes in File for eachType ...
|
||||
const indexes = XValueTools.findAllIndexes(
|
||||
Object.values(LocalizationResourceIdentifiers),
|
||||
content
|
||||
);
|
||||
if (!XValueTools.hasChildArray(indexes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to Parse Content by indexes ...
|
||||
for (const idx of indexes) {
|
||||
//
|
||||
let identifierToken = content.substring(idx, idx + LocalizationResourceIdentifiers.ThisAppResourceIDs.length);
|
||||
if (identifierToken.includes(LocalizationResourceIdentifiers.ThisAppResourceIDs)) {
|
||||
identifierToken = identifierToken.includes(LocalizationResourceIdentifiers.ThisAppResourceIDs);
|
||||
} else if (identifierToken.includes(LocalizationResourceIdentifiers.ThisResourceIDs)) {
|
||||
identifierToken = LocalizationResourceIdentifiers.ThisResourceIDs;
|
||||
} else if (identifierToken.includes(LocalizationResourceIdentifiers.XAppResourceIDs)) {
|
||||
identifierToken = LocalizationResourceIdentifiers.XAppResourceIDs;
|
||||
} else if (identifierToken.includes(LocalizationResourceIdentifiers.XResourceIDs)) {
|
||||
identifierToken = LocalizationResourceIdentifiers.XResourceIDs;
|
||||
} else if (identifierToken.includes(LocalizationResourceIdentifiers.ResourceIDs)) {
|
||||
identifierToken = LocalizationResourceIdentifiers.ResourceIDs;
|
||||
} else {
|
||||
identifierToken = undefined;
|
||||
}
|
||||
|
||||
//
|
||||
if (!XValueTools.isValidArg(identifierToken)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
let endIndex = XValueTools.findNearestIndex(
|
||||
[
|
||||
';',
|
||||
'\"',
|
||||
',',
|
||||
' ',
|
||||
')',
|
||||
'\n'
|
||||
],
|
||||
content,
|
||||
idx,
|
||||
true
|
||||
);
|
||||
|
||||
//
|
||||
const identifier = content
|
||||
.substring(idx, endIndex)
|
||||
.replace(identifierToken, '');
|
||||
if (XValueTools.isValidArg(identifier)) {
|
||||
//
|
||||
switch (identifierToken) {
|
||||
//
|
||||
// ResourceIDs ...
|
||||
case LocalizationResourceIdentifiers.ResourceIDs:
|
||||
case LocalizationResourceIdentifiers.XResourceIDs:
|
||||
case LocalizationResourceIdentifiers.ThisResourceIDs:
|
||||
if (!result.resourceIds.includes(identifier)) {
|
||||
result.resourceIds.push(identifier);
|
||||
}
|
||||
break;
|
||||
|
||||
//
|
||||
// AppResourceIDs ...
|
||||
case LocalizationResourceIdentifiers.XAppResourceIDs:
|
||||
case LocalizationResourceIdentifiers.ThisAppResourceIDs:
|
||||
if (!result.appResourceIds.includes(identifier)) {
|
||||
result.appResourceIds.push(identifier);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LocaleResourceItemDescriptor ...
|
||||
function isLocaleResourceItemDescriptor(value) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
result = value &&
|
||||
value.hasOwnProperty('id') &&
|
||||
value.hasOwnProperty('value');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
function createLocaleResourceItemDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
id: '',
|
||||
value: ''
|
||||
};
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region id ...
|
||||
if (XValueTools.isValidArg(value.id)) {
|
||||
result.id = value.id;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region value ...
|
||||
if (XValueTools.isValidArg(value.value)) {
|
||||
result.value = value.value;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LocalizationDescriptor ...
|
||||
function isLocalizationDescriptor(value) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
result = value &&
|
||||
value.hasOwnProperty('name') &&
|
||||
value.hasOwnProperty('locale') &&
|
||||
value.hasOwnProperty('language') &&
|
||||
value.hasOwnProperty('direction') &&
|
||||
value.hasOwnProperty('resources') &&
|
||||
Array.isArray(value.resources) &&
|
||||
(XValueTools.hasChildArray(value.resources) ?
|
||||
value.resources.every(r => isLocaleResourceItemDescriptor(r)) : true);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
function createLocalizationDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
name: '',
|
||||
locale: '',
|
||||
language: '',
|
||||
direction: '',
|
||||
resources: [
|
||||
createLocaleResourceItemDescriptor()
|
||||
]
|
||||
};
|
||||
result.resources.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region name ...
|
||||
if (XValueTools.isValidArg(value.name)) {
|
||||
result.name = value.name;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region locale ...
|
||||
if (XValueTools.isValidArg(value.locale)) {
|
||||
result.locale = value.locale;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region language ...
|
||||
if (XValueTools.isValidArg(value.language)) {
|
||||
result.language = value.language;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region direction ...
|
||||
if (XValueTools.isValidArg(value.direction)) {
|
||||
result.direction = value.direction;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region resources ...
|
||||
if (
|
||||
XValueTools.hasChildArray(value.resources) &&
|
||||
value.resources.every(r => isLocaleResourceItemDescriptor(r))
|
||||
) {
|
||||
result.resources = [
|
||||
...value.resources
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
function extractLocalizationDescriptors(
|
||||
constDescriptor = XConstDescriptor.createDescriptor()
|
||||
) {
|
||||
//
|
||||
let result = [
|
||||
createLocalizationDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!constDescriptor ||
|
||||
!XConstDescriptor.isDescriptor(constDescriptor) ||
|
||||
!XValueTools.hasChildArray(constDescriptor.content.childs)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// extract childs of content ...
|
||||
for (const child of constDescriptor.content.childs) {
|
||||
//
|
||||
const localizationDescriptor = createLocalizationDescriptor();
|
||||
for (const value of child.value) {
|
||||
//
|
||||
if (value.key !== 'resources') {
|
||||
localizationDescriptor[value.key] = XValueTools.toStringExpression(value.value);
|
||||
} else {
|
||||
localizationDescriptor[value.key] = value.value.map(v => {
|
||||
//
|
||||
const id = XValueTools
|
||||
.toStringExpression(
|
||||
v.value.find(
|
||||
vv => vv.key === 'id')?.value
|
||||
);
|
||||
|
||||
//
|
||||
const value = XValueTools
|
||||
.toStringExpression(
|
||||
v.value.find(
|
||||
vv => vv.key === 'value')?.value
|
||||
);
|
||||
|
||||
//
|
||||
const result = createLocaleResourceItemDescriptor({
|
||||
id,
|
||||
value,
|
||||
});
|
||||
|
||||
//
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
result.push(localizationDescriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region ResourceIDUsedCase ...
|
||||
/**
|
||||
* create an empty/filled LocaleResourceIDUsedCaseDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value value provider for filling ...
|
||||
* @returns an instance of Specific Descriptor ...
|
||||
*/
|
||||
function createLocaleResourceIDUsedCaseDescriptor(value) {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = {
|
||||
resourceID: '',
|
||||
usedCases: [
|
||||
''
|
||||
],
|
||||
};
|
||||
result.usedCases.pop();
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region resourceID ...
|
||||
if (XValueTools.isValidArg(value.resourceID)) {
|
||||
result.resourceID = value.resourceID;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region usedCases ...
|
||||
if (XValueTools.hasChildArray(value.usedCases)) {
|
||||
result.usedCases = [
|
||||
...value.usedCases
|
||||
];
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is LocaleResourceIDUsedCaseDescriptor instance or not ...
|
||||
*
|
||||
* @param {any} value proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isLocaleResourceIDUsedCaseDescriptor(value) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
result = value &&
|
||||
value.hasOwnProperty('resourceID') &&
|
||||
value.hasOwnProperty('usedCases') &&
|
||||
Array.isArray(value.usedCases);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Moduile Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
LocalizationResourceIdentifiers,
|
||||
|
||||
//
|
||||
isResourceIDsDescriptor,
|
||||
createResourceIDsDescriptor,
|
||||
extractResourceIDsDescriptor,
|
||||
extractResourceIDsDescriptorFromContent,
|
||||
|
||||
//
|
||||
isLocaleResourceItemDescriptor,
|
||||
createLocaleResourceItemDescriptor,
|
||||
|
||||
//
|
||||
isLocalizationDescriptor,
|
||||
createLocalizationDescriptor,
|
||||
extractLocalizationDescriptors,
|
||||
|
||||
//
|
||||
isLocaleResourceIDUsedCaseDescriptor,
|
||||
createLocaleResourceIDUsedCaseDescriptor,
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
const XValueTools = require('../tools/x-value.tools');
|
||||
const XBaseDescriptor = require('./x-base.descriptor');
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* check an object instance is typeDescriptor or not ...
|
||||
*
|
||||
* @param {any} object proposed object to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDescriptor(object) {
|
||||
//
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
let result = false;
|
||||
result =
|
||||
object.hasOwnProperty('raw') &&
|
||||
object.hasOwnProperty('name') &&
|
||||
object.hasOwnProperty('content') &&
|
||||
object.hasOwnProperty('isExported');
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve base or filled TypeDescriptor object instance ...
|
||||
*
|
||||
* @param {any} value a value provider object ...
|
||||
* @returns an instance of TypeDescriptor object ...
|
||||
*/
|
||||
function createDescriptor(value) {
|
||||
//
|
||||
let result = {
|
||||
raw: '',
|
||||
name: '',
|
||||
content: '',
|
||||
isExported: false,
|
||||
};
|
||||
|
||||
//
|
||||
//#region Apply Value ...
|
||||
if (value) {
|
||||
//
|
||||
//#region raw ...
|
||||
if (XValueTools.isValidArg(value.raw)) {
|
||||
result.raw = value.raw;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region name ...
|
||||
if (XValueTools.isValidArg(value.name)) {
|
||||
result.name = value.name;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region content ...
|
||||
if (XValueTools.isValidArg(value.content)) {
|
||||
result.content = value.content;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region isExported ...
|
||||
if (!!value.isExported) {
|
||||
result.isExported = true;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts an instance of Descriptor to Expression ...
|
||||
*
|
||||
* @param descriptor an instance of TypeDescriptor ...
|
||||
* @returns creator string ...
|
||||
*/
|
||||
function toExpression(descriptor = createDescriptor()) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Validate Arg ...
|
||||
if (!isDescriptor(descriptor)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result += (
|
||||
!!descriptor.isExported ?
|
||||
XBaseDescriptor.ExpressionKeys.Export + ' ' :
|
||||
''
|
||||
) +
|
||||
XBaseDescriptor.ExpressionKeys.Type +
|
||||
' ' +
|
||||
descriptor.name +
|
||||
' = ' +
|
||||
descriptor.content
|
||||
+ ';';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists TypeDescriptors ...
|
||||
*
|
||||
* @param {string} file a file path ...
|
||||
* @returns a collection of TypeDescriptor ...
|
||||
*/
|
||||
async function extractDescriptors(file = '') {
|
||||
//
|
||||
if (!XFileTools.isFileExists(file)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
const fileContent = await XFileTools.readFile(file);
|
||||
if (!XValueTools.isValidArg(fileContent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
//
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
result = extractDescriptorsFromContent(fileContent);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract all exists TypeDescriptors ...
|
||||
*
|
||||
* @param {string} content a file content ...
|
||||
* @returns a collection of TypeDescriptor ...
|
||||
*/
|
||||
function extractDescriptorsFromContent(content = '') {
|
||||
//
|
||||
// Prepare Result ...
|
||||
let result = [
|
||||
createDescriptor()
|
||||
];
|
||||
result.pop();
|
||||
|
||||
//
|
||||
// Validate Args ...
|
||||
if (
|
||||
!XValueTools.isValidArg(content) ||
|
||||
!content.includes(XBaseDescriptor.ExpressionKeys.Type)
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract all key Indexes ...
|
||||
const keyIndexes = XBaseDescriptor.
|
||||
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Type, content);
|
||||
|
||||
//
|
||||
// Validate them ...
|
||||
if (!XValueTools.hasChildArray(keyIndexes)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through indexes ...
|
||||
for (const index of keyIndexes) {
|
||||
//
|
||||
// Check Type after befre content ...
|
||||
let startIndex = index - 1;
|
||||
let endIndex = index + XBaseDescriptor.ExpressionKeys.Type.length + 1;
|
||||
|
||||
//
|
||||
// create an empty instance of descriptor ...
|
||||
let descriptor = {
|
||||
...createDescriptor()
|
||||
}
|
||||
|
||||
//
|
||||
//#region Name extractor ...
|
||||
const nameEndIndex = content.indexOf('=', index);
|
||||
identifier = content
|
||||
.substring(index + XBaseDescriptor.ExpressionKeys.Type.length, nameEndIndex)
|
||||
.trim();
|
||||
if (XValueTools.isValidArg(identifier)) {
|
||||
descriptor.name = identifier;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Extract isExported ...
|
||||
const isExported = XBaseDescriptor.checkIsExported(index, content);
|
||||
descriptor.isExported = isExported;
|
||||
if (isExported) {
|
||||
startIndex = index - XBaseDescriptor.ExpressionKeys.Export.length - 1;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Extract raw content ...
|
||||
identifier = content.substring(startIndex);
|
||||
startIndex = 0;
|
||||
endIndex = XValueTools.findNearestIndex(
|
||||
[
|
||||
';',
|
||||
'{',
|
||||
'\n'
|
||||
]
|
||||
, identifier
|
||||
);
|
||||
const nearestChar = identifier.charAt(endIndex);
|
||||
if (nearestChar === '{') {
|
||||
//
|
||||
const closedItemsIndexes = XValueTools.findClosedContentIndexes('{', '}', identifier, endIndex);
|
||||
if (!XValueTools.hasChildArray(closedItemsIndexes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
endIndex = closedItemsIndexes[0].end;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
identifier = identifier
|
||||
.substring(startIndex, endIndex)
|
||||
.trim();
|
||||
if (XValueTools.isValidArg(identifier)) {
|
||||
descriptor.raw = identifier;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Parse Content ...
|
||||
startIndex = identifier.indexOf('=', 0);
|
||||
identifier = identifier
|
||||
.substring(startIndex + 1)
|
||||
.trim();
|
||||
identifier = XBaseDescriptor.clearContent(identifier);
|
||||
if (XValueTools.isValidArg(identifier)) {
|
||||
descriptor.content = identifier;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
result.push(descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
isDescriptor,
|
||||
toExpression,
|
||||
createDescriptor,
|
||||
extractDescriptors,
|
||||
extractDescriptorsFromContent,
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
//
|
||||
const XElectronChannel = {
|
||||
Default: 'xMessage',
|
||||
Handshake: 'xHandshake',
|
||||
FileService: 'xFileService',
|
||||
ProjectsService: 'xProjectsService',
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
XElectronChannel: XElectronChannel,
|
||||
|
||||
//
|
||||
XElectronMessage: class XElectronMessage {
|
||||
//
|
||||
constructor(
|
||||
sender = '',
|
||||
reciever = '',
|
||||
message = '',
|
||||
payload = undefined,
|
||||
channel = undefined,
|
||||
timestamp = undefined,
|
||||
) {
|
||||
//
|
||||
if (!timestamp) {
|
||||
timestamp = Date.now();
|
||||
}
|
||||
|
||||
//
|
||||
if (!channel) {
|
||||
channel = XElectronChannel.Default;
|
||||
}
|
||||
|
||||
//
|
||||
this.sender = sender;
|
||||
this.reciever = reciever;
|
||||
this.payload = payload;
|
||||
this.message = message;
|
||||
this.timestamp = timestamp;
|
||||
this.channel = channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const Path = require('path');
|
||||
const XValueTools = require('./x-value.tools');
|
||||
|
||||
/**
|
||||
* required folder names ...
|
||||
*/
|
||||
const FolderNames = {
|
||||
Documents: 'Documents',
|
||||
}
|
||||
|
||||
/**
|
||||
* current os path separators ...
|
||||
*/
|
||||
const PathSeparator = Path.sep;
|
||||
|
||||
/**
|
||||
* current directory ...
|
||||
*/
|
||||
const CurrentDir = __dirname;
|
||||
|
||||
//
|
||||
//#region Global ...
|
||||
/**
|
||||
* retrieve a path status ...
|
||||
*
|
||||
* @param {string} path a path value to check ...
|
||||
* @returns an stat object ...
|
||||
*/
|
||||
function getStatus(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//
|
||||
return fs.statSync(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve user's Document path ...
|
||||
*
|
||||
* @returns a path ...
|
||||
*/
|
||||
function getDocumentsPath() {
|
||||
return Path.join(os.homedir(), FolderNames.Documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve user's Document contents ...
|
||||
*
|
||||
* @returns resources contents as string array ...
|
||||
*/
|
||||
function getDocumentsContents() {
|
||||
return getDirectoryContents(getDocumentsPath());
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Path ...
|
||||
/**
|
||||
* retrieve the base name of specific address path ...
|
||||
*
|
||||
* @param {string} path address of file or folder ...
|
||||
* @returns string ...
|
||||
*/
|
||||
function basename(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
const result = Path.basename(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* join several path segments together ...
|
||||
*
|
||||
* @param {...string} path path params ...
|
||||
* @returns a joined paths ...
|
||||
*/
|
||||
function joinPath(...path) {
|
||||
return Path.join(...path);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region File ...
|
||||
/**
|
||||
* determines a path destination is a file or not ...
|
||||
*
|
||||
* @param {string} path a path value to check ...
|
||||
* @returns a boolean value ...
|
||||
*/
|
||||
function isFileExists(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
const stat = getStatus(path);
|
||||
if (!stat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
return stat.isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a file ...
|
||||
*
|
||||
* @param {string} path a file path ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function removeFile(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isFileExists(path)) {
|
||||
resolve(false);
|
||||
}
|
||||
|
||||
//
|
||||
fs.unlink(path, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* copy a file to destination path ...
|
||||
*
|
||||
* @param {string} source source file path ...
|
||||
* @param {string} dest dest folder path ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function copyFile(
|
||||
source = '',
|
||||
dest = ''
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (
|
||||
!isFileExists(source) ||
|
||||
!isDirectoryExists(dest)
|
||||
) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const destFilePath = Path.join(dest, Path.basename(source));
|
||||
fs.copyFile(source, destFilePath, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* reading specified file content ...
|
||||
*
|
||||
* @param {string} path a file path ...
|
||||
* @returns {Promise<string>} file content ...
|
||||
*/
|
||||
function readFile(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isFileExists(path)) {
|
||||
resolve('');
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readFile(path, 'utf8', (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* write content to a file ...
|
||||
*
|
||||
* @param {string} path a file path ...
|
||||
* @param {string} content the content which going to write to the file ...
|
||||
* @param {bool} overwrite determines file overwrite if exists ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function writeFile(
|
||||
path = '',
|
||||
content = '',
|
||||
overwrite = true
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (isFileExists(path) && !overwrite) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Normalize Content ...
|
||||
content = XValueTools.isValidArg(content) ?
|
||||
content :
|
||||
'';
|
||||
|
||||
//
|
||||
fs.writeFile(path, content, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* create a file ...
|
||||
*
|
||||
* @param {string} path file path ...
|
||||
* @param {string} fileName file name ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function createFile(
|
||||
path = '',
|
||||
fileName = ''
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
const filePath = Path.join(path, fileName);
|
||||
if (
|
||||
isFileExists(filePath) ||
|
||||
!XValueTools.isValidArg(path) ||
|
||||
!XValueTools.isValidArg(fileName)
|
||||
) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.writeFile(filePath, '', (err) => {
|
||||
//
|
||||
if (err) {
|
||||
//
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a file name extension ...
|
||||
*
|
||||
* @param {string} name
|
||||
* @returns {string} name without extension ...
|
||||
*/
|
||||
function removeFileExtension(name = '') {
|
||||
return name.substring(0, name.lastIndexOf('.')) || name;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Directory ...
|
||||
/**
|
||||
* create a directory ...
|
||||
*
|
||||
* @param {string} path destination path including dir name ...
|
||||
* @param {boolean} recursive create directories recursively ...
|
||||
* @returns action done or not ...
|
||||
*/
|
||||
function createDirectory(
|
||||
path = '',
|
||||
recursive = true
|
||||
) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
if (
|
||||
isDirectoryExists(path) ||
|
||||
!XValueTools.isValidArg(path)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
fs.mkdirSync(path, { recursive: recursive });
|
||||
result = true;
|
||||
return result;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a directory ...
|
||||
*
|
||||
* @param {string} path destination path including dir name ...
|
||||
* @param {boolean} recursive removes directories recursively ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
function removeDirectory(
|
||||
path = '',
|
||||
recursive = false
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.rm(path, {
|
||||
recursive
|
||||
}, (err) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* determines a path destination is a directory or not ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns represent destnation path is Directory or not ...
|
||||
*/
|
||||
function isDirectoryExists(path = '') {
|
||||
//
|
||||
if (!XValueTools.isValidArg(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
const isExists = fs.existsSync(path);
|
||||
if (!isExists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
const stat = getStatus(path);
|
||||
if (!stat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
const result = stat.isDirectory();
|
||||
return result;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a directory content ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns {Promise<string[]>} a collection of folder files ...
|
||||
*/
|
||||
function getDirectoryContents(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readdir(path, (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a directory files ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns {Promise<string[]>} a collection of folder files ...
|
||||
*/
|
||||
function getDirectoryFiles(
|
||||
path = '',
|
||||
containsHiddenFiles = false
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readdir(path, (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (!containsHiddenFiles) {
|
||||
content = content.filter(c => !c.startsWith('.'))
|
||||
}
|
||||
|
||||
//
|
||||
const result = [];
|
||||
content
|
||||
.forEach(c => {
|
||||
//
|
||||
const cPath = Path.join(path, c);
|
||||
if (isFileExists(cPath)) {
|
||||
result.push(c);
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a directory folders ...
|
||||
*
|
||||
* @param {string} path a folder path ...
|
||||
* @returns {Promise<string[]>} a collection of folder names ...
|
||||
*/
|
||||
function getDirectoryFolders(path = '') {
|
||||
return new Promise((resolve) => {
|
||||
//
|
||||
if (!isDirectoryExists(path)) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
fs.readdir(path, (err, content) => {
|
||||
//
|
||||
if (err) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const result = [];
|
||||
content.forEach(c => {
|
||||
//
|
||||
const cPath = Path.join(path, c);
|
||||
if (isDirectoryExists(cPath)) {
|
||||
result.push(c);
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* copy a folder with all of it's content to dest ...
|
||||
*
|
||||
* @param {string} source source folder path ...
|
||||
* @param {string} dest dest folder path ...
|
||||
* @returns {Promise<boolean>} action done or not ...
|
||||
*/
|
||||
async function copyFolder(
|
||||
source = '',
|
||||
dest = ''
|
||||
) {
|
||||
//
|
||||
if (
|
||||
!isDirectoryExists(source) ||
|
||||
!XValueTools.isValidArg(dest) ||
|
||||
!XValueTools.isValidArg(source)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
const folderName = Path.basename(source);
|
||||
const destPath = Path.join(dest, folderName);
|
||||
|
||||
//
|
||||
// Create Dest Path folder if not exists ...
|
||||
if (!isDirectoryExists(destPath)) {
|
||||
//
|
||||
let result = createDirectory(destPath, true);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Files ...
|
||||
const files = await getDirectoryFiles(source);
|
||||
if (files && files.constructor === Array && files.length > 0) {
|
||||
//
|
||||
const filesPromises = files.map(file => copyFile(Path.join(source, file), destPath));
|
||||
const filesResult = (await Promise.all(filesPromises)).every(r => !!r);
|
||||
if (!filesResult) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Folders ...
|
||||
const folders = await getDirectoryFolders(source);
|
||||
if (folders && folders.constructor === Array && folders.length > 0) {
|
||||
//
|
||||
const folderPromises = folders.map(folder => copyFolder(Path.join(source, folder), destPath));
|
||||
const filesResult = (await Promise.all(folderPromises)).every(r => !!r);
|
||||
if (!filesResult) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return true;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
CurrentDir,
|
||||
FolderNames,
|
||||
PathSeparator,
|
||||
|
||||
//
|
||||
getStatus,
|
||||
getDocumentsPath,
|
||||
getDocumentsContents,
|
||||
|
||||
//
|
||||
basename,
|
||||
joinPath,
|
||||
|
||||
//
|
||||
copyFile,
|
||||
readFile,
|
||||
writeFile,
|
||||
createFile,
|
||||
removeFile,
|
||||
isFileExists,
|
||||
removeFileExtension,
|
||||
|
||||
//
|
||||
copyFolder,
|
||||
createDirectory,
|
||||
removeDirectory,
|
||||
createDirectory,
|
||||
removeDirectory,
|
||||
isDirectoryExists,
|
||||
isDirectoryExists,
|
||||
getDirectoryFiles,
|
||||
getDirectoryFolders,
|
||||
getDirectoryContents,
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
|
||||
const baseLogTag = 'XFrameworkElectronApp';
|
||||
let enableLogging = true;
|
||||
|
||||
/**
|
||||
* Log Tags ...
|
||||
*/
|
||||
const XLogTag = {
|
||||
Debug: 'debug',
|
||||
Info: 'info',
|
||||
Warn: 'warn',
|
||||
Error: 'error'
|
||||
};
|
||||
|
||||
/**
|
||||
* retrieve an instance of XLogMessage ...
|
||||
*
|
||||
* @param {string} tag tag of logging ...
|
||||
* @param {string} message content of log message ...
|
||||
* @param {array of any} args args of content which required to logging ...
|
||||
* @param {number} timestamp logging time ...
|
||||
*
|
||||
* @returns an instance of log message object ...
|
||||
*/
|
||||
function XLogMessage(tag, message, args, timestamp) {
|
||||
//
|
||||
if (!tag) {
|
||||
throw 'Tag not provided ...';
|
||||
}
|
||||
|
||||
//
|
||||
if (!message) {
|
||||
throw 'Message not provided ...';
|
||||
}
|
||||
|
||||
//
|
||||
if (!args) {
|
||||
args = [];
|
||||
}
|
||||
|
||||
//
|
||||
if (!timestamp) {
|
||||
timestamp = new Date().getTime();
|
||||
}
|
||||
|
||||
//
|
||||
return {
|
||||
tag,
|
||||
message,
|
||||
args,
|
||||
timestamp,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* log data ...
|
||||
*
|
||||
* @param {XLogMessage} message
|
||||
*/
|
||||
function log(message) {
|
||||
//
|
||||
if (!message || !message.tag || !message.message || !enableLogging) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
message.timestamp = new Date().getTime();
|
||||
|
||||
//
|
||||
switch (message.tag) {
|
||||
//
|
||||
case XLogTag.Debug:
|
||||
logDebug(message);
|
||||
break;
|
||||
//
|
||||
case XLogTag.Info:
|
||||
logInfo(message);
|
||||
break;
|
||||
//
|
||||
case XLogTag.Warn:
|
||||
logWarn(message);
|
||||
break;
|
||||
//
|
||||
case XLogTag.Error:
|
||||
logError(message);
|
||||
break;
|
||||
|
||||
//
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Debug ...
|
||||
*
|
||||
* @param {XLogMessage} message
|
||||
*/
|
||||
function logDebug(message) {
|
||||
//
|
||||
if (!message || !message.message || !enableLogging || message.tag !== XLogTag.Debug) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
message.timestamp = new Date().getTime();
|
||||
|
||||
//
|
||||
console.debug(`${baseLogTag}:${message.tag} => ${message.message}`, ...message.args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Info ...
|
||||
*
|
||||
* @param {XLogMessage} message
|
||||
*/
|
||||
function logInfo(message) {
|
||||
//
|
||||
if (!message || !message.message || !enableLogging || message.tag !== XLogTag.Info) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
message.timestamp = new Date().getTime();
|
||||
|
||||
//
|
||||
console.info(`${baseLogTag}:${message.tag} => ${message.message}`, ...message.args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Warn ...
|
||||
*
|
||||
* @param {XLogMessage} message
|
||||
*/
|
||||
function logWarn(message) {
|
||||
//
|
||||
if (!message || !message.message || !enableLogging || message.tag !== XLogTag.Warn) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
message.timestamp = new Date().getTime();
|
||||
|
||||
//
|
||||
console.warn(`${baseLogTag}:${message.tag} => ${message.message}`, ...message.args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Error ...
|
||||
*
|
||||
* @param {XLogMessage} message
|
||||
*/
|
||||
function logError(message) {
|
||||
//
|
||||
if (!message || !message.message || !enableLogging || message.tag !== XLogTag.Error) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
message.timestamp = new Date().getTime();
|
||||
|
||||
//
|
||||
console.error(`${baseLogTag}:${message.tag} => ${message.message}`, ...message.args);
|
||||
}
|
||||
|
||||
//
|
||||
// Module Eports ...
|
||||
module.exports = {
|
||||
//
|
||||
enableLogging: () => {
|
||||
enableLogging = true;
|
||||
},
|
||||
disableLogging: () => {
|
||||
enableLogging = false;
|
||||
},
|
||||
isLoggingEnable: () => {
|
||||
return enableLogging;
|
||||
},
|
||||
//
|
||||
XLogTag: XLogTag,
|
||||
XLogMessage: XLogMessage,
|
||||
log: log,
|
||||
logDebug: logDebug,
|
||||
logInfo: logInfo,
|
||||
logWarn: logWarn,
|
||||
logError: logError,
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const os = require('os');
|
||||
const process = require('process');
|
||||
const { exec } = require("child_process");
|
||||
const XFileTools = require('../tools/x-file.tools');
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
//
|
||||
const OS = {
|
||||
Aix: 'aix',
|
||||
Darwin: 'darwin',
|
||||
FreeBSD: 'freebsd',
|
||||
Linux: 'linux',
|
||||
OpenBSD: 'openbsd',
|
||||
SnOS: 'sunos',
|
||||
Windows: 'win32'
|
||||
}
|
||||
|
||||
//
|
||||
const isWindows = process.platform === OS.Windows;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
//
|
||||
//#region Pure shell commands ...
|
||||
/**
|
||||
* execute a command using NodeJS on shell ...
|
||||
*
|
||||
* @param {string} cmd command to execute ...
|
||||
* @param {string} cwd working directory ...
|
||||
*
|
||||
* @returns Promise<any, errr> instance ...
|
||||
*/
|
||||
function execute(cmd, cwd) {
|
||||
return new Promise((resolve, reject) => {
|
||||
//
|
||||
if (!cmd || cmd.toString().length === 0 || (cwd && !XFileTools.isDirectoryExists(cwd))) {
|
||||
reject('invalid args ...');
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
exec(cmd, { cwd }, (err, result, stdError) => {
|
||||
//
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (stdError) {
|
||||
//
|
||||
// reject(stdError);
|
||||
// return;
|
||||
}
|
||||
|
||||
//
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* determines a command exists on host or not ...
|
||||
*
|
||||
* @param {string} name specific command name ...
|
||||
*
|
||||
* @returns boolean Promise ...
|
||||
*/
|
||||
function checkCommandExists(name) {
|
||||
return new Promise(resolve => {
|
||||
//
|
||||
if (!name) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const cmd = isWindows ? `${name} >nul 2>&1` : `type ${name} >/dev/null 2>&1`;
|
||||
execute(cmd).then(result => {
|
||||
resolve(true);
|
||||
})
|
||||
.catch(err => {
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region required commands state ...
|
||||
/**
|
||||
* check al required commands exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async function isRequiredCommandsExists() {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
// const isTarExists = await isTarCommandExists();
|
||||
// const isCatExists = await isCatCommandExists();
|
||||
// const isGrepExists = await isGrepCommandExists();
|
||||
// const isSedExists = await isSedCommandExists();
|
||||
// const isNpmExists = await isNpmCommandExists();
|
||||
const isNgExists = await isNgCommandExists();
|
||||
const isIonicExists = await isIonicCommandExists();
|
||||
const isCordovaExists = await isCordovaCommandExists();
|
||||
|
||||
//
|
||||
result = isNgExists &&
|
||||
isIonicExists &&
|
||||
isCordovaExists;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve required commands state object ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async function getRequiredCommandsStates() {
|
||||
//
|
||||
const result = {};
|
||||
|
||||
//
|
||||
// const isTarExists = await isTarCommandExists();
|
||||
// const isCatExists = await isCatCommandExists();
|
||||
// const isGrepExists = await isGrepCommandExists();
|
||||
// const isSedExists = await isSedCommandExists();
|
||||
// const isNpmExists = await isNpmCommandExists();
|
||||
const isNgExists = await isNgCommandExists();
|
||||
const isIonicExists = await isIonicCommandExists();
|
||||
const isCordovaExists = await isCordovaCommandExists();
|
||||
|
||||
//
|
||||
result['ng'] = isNgExists;
|
||||
result['ionic'] = isIonicExists;
|
||||
result['cordova'] = isCordovaExists;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Commonly used Command Checkers ...
|
||||
/**
|
||||
* determines ng command exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function isNgCommandExists() {
|
||||
return checkCommandExists('ng');
|
||||
}
|
||||
|
||||
/**
|
||||
* determines ionic command exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function isIonicCommandExists() {
|
||||
return checkCommandExists('ionic');
|
||||
}
|
||||
|
||||
/**
|
||||
* determines cordova command exists or not ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function isCordovaCommandExists() {
|
||||
return checkCommandExists('cordova');
|
||||
}
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
execute,
|
||||
checkCommandExists,
|
||||
isRequiredCommandsExists,
|
||||
getRequiredCommandsStates,
|
||||
|
||||
//
|
||||
// isFxCommandExists,
|
||||
// isTarCommandExists,
|
||||
// isCatCommandExists,
|
||||
// isSedCommandExists,
|
||||
// isNpmCommandExists,
|
||||
// isGrepCommandExists,
|
||||
isNgCommandExists,
|
||||
isIonicCommandExists,
|
||||
isCordovaCommandExists,
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
/**
|
||||
* all supported data types ...
|
||||
*/
|
||||
const DataTypes = {
|
||||
Null: 'null',
|
||||
Date: 'date',
|
||||
Array: 'array',
|
||||
Object: 'object',
|
||||
String: 'string',
|
||||
Number: 'number',
|
||||
Unknown: 'unknown',
|
||||
Boolean: 'boolean',
|
||||
Function: 'function',
|
||||
Undefined: 'undefined',
|
||||
};
|
||||
|
||||
/**
|
||||
* detect type of a content ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function getType(value) {
|
||||
//
|
||||
const type = typeof value;
|
||||
|
||||
//
|
||||
let result = DataTypes.Unknown;
|
||||
let dateIdentifier = '[object Date]';
|
||||
let constructor = value && value.constructor ?
|
||||
value.constructor.toString() :
|
||||
'';
|
||||
|
||||
//
|
||||
switch (type) {
|
||||
//
|
||||
case 'undefined':
|
||||
result = DataTypes.Undefined;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'boolean':
|
||||
result = DataTypes.Boolean;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'string':
|
||||
result = DataTypes.String;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'number':
|
||||
result = DataTypes.Number;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'function':
|
||||
result = DataTypes.Function;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'object':
|
||||
//
|
||||
// Null ...
|
||||
if (value === null) {
|
||||
result = DataTypes.Null;
|
||||
} else
|
||||
//
|
||||
// Array ...
|
||||
if (Array.isArray(value)) {
|
||||
result = DataTypes.Array;
|
||||
} else
|
||||
//
|
||||
// Data ...
|
||||
if (
|
||||
value instanceof Date ||
|
||||
isFunction(value.getMonth) ||
|
||||
constructor.includes(dateIdentifier) ||
|
||||
Object.prototype.toString.call(value) === dateIdentifier
|
||||
) {
|
||||
result = DataTypes.Date;
|
||||
} else
|
||||
//
|
||||
// Object ...
|
||||
{
|
||||
result = DataTypes.Object;
|
||||
}
|
||||
break;
|
||||
|
||||
//
|
||||
default:
|
||||
result = DataTypes.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve an object constructor ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function getConstructor(value) {
|
||||
//
|
||||
const result = value && value.constructor ?
|
||||
value.constructor.toString() :
|
||||
'';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve an object prototype ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function getPrototype(value) {
|
||||
//
|
||||
const result = value ?
|
||||
Object.prototype.toString.call(value) :
|
||||
'';
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is null or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isNull(value) {
|
||||
return getType(value) === DataTypes.Null;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is undefined or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isUndefined(value) {
|
||||
return getType(value) === DataTypes.Undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is null or undefined or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isNullOrUndefined(value) {
|
||||
return isNull(value) || isUndefined(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is a date or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isDate(value) {
|
||||
return getType(value) === DataTypes.Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is number or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isNumber(value) {
|
||||
return getType(value) === DataTypes.Number;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is string or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isString(value) {
|
||||
return getType(value) === DataTypes.String;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is boolean or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isBoolean(value) {
|
||||
return getType(value) === DataTypes.Boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is an Array or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isArray(value) {
|
||||
return getType(value) === DataTypes.Array;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is and Object or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isObject(value) {
|
||||
return getType(value) === DataTypes.Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* check an object is a Function or not ...
|
||||
*
|
||||
* @param {any} value the content which going to check ...
|
||||
* @returns
|
||||
*/
|
||||
function isFunction(value) {
|
||||
return getType(value) === DataTypes.Function;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
//
|
||||
DataTypes,
|
||||
|
||||
//
|
||||
getType,
|
||||
getConstructor,
|
||||
getPrototype,
|
||||
isNull,
|
||||
isUndefined,
|
||||
isNullOrUndefined,
|
||||
isDate,
|
||||
isNumber,
|
||||
isString,
|
||||
isBoolean,
|
||||
isArray,
|
||||
isObject,
|
||||
isFunction,
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
//#region Imports ...
|
||||
const uuid = require("uuid");
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
const DEFAULT_NAMESPACE = "SaherElm IT Center";
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* generate a uniqu identifier ...
|
||||
*
|
||||
* @param {string} prefix the prefix of generated uuid ...
|
||||
* @param {string} content the additional content which added to generated uuid ...
|
||||
* @param {string} nameSpace the proposed name space for generating uuid ...
|
||||
* @returns a unique universal uuid ...
|
||||
*/
|
||||
function generateUuid(
|
||||
prefix,
|
||||
content,
|
||||
nameSpace = DEFAULT_NAMESPACE
|
||||
) {
|
||||
//
|
||||
const uId = content ? uuid.v5(content, nameSpace) : uuid.v4();
|
||||
const result = prefix ? `${prefix}_${uId}` : uId;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Module Exports ...
|
||||
module.exports = {
|
||||
DEFAULT_NAMESPACE,
|
||||
generateUuid,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* main storage object ...
|
||||
*/
|
||||
const windows = {};
|
||||
|
||||
/**
|
||||
* retrieve all exists window id's ...
|
||||
*
|
||||
* @returns an array of strings which represents window id's ...
|
||||
*/
|
||||
function keys() {
|
||||
return Object.keys(windows);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve all available windows ...
|
||||
*
|
||||
* @returns an array of strings which represent BrowserWindow Objects ...
|
||||
*/
|
||||
function values() {
|
||||
return Object.values(windows);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve count of available windows ...
|
||||
*
|
||||
* @returns number
|
||||
*/
|
||||
function count() {
|
||||
return Object.keys(windows).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* check a BrowserWindow id exists or not ...
|
||||
*
|
||||
* @param {string} key window id ...
|
||||
* @returns a boolean value which represent window exists or not ...
|
||||
*/
|
||||
function has(key) {
|
||||
//
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
return keys()
|
||||
.includes(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve a window by providing it's id ...
|
||||
*
|
||||
* @param {string} key window id ...
|
||||
* @returns an instance of Browserwindow instance ...
|
||||
*/
|
||||
function get(key) {
|
||||
//
|
||||
if (!has(key)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//
|
||||
return windows[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* set a window by it's id ...
|
||||
*
|
||||
* @param {string} key window id ...
|
||||
* @param {BrowserWindow} value specified window instance ...
|
||||
* @returns a boolean value ...
|
||||
*/
|
||||
function set(key, value) {
|
||||
//
|
||||
try {
|
||||
windows[key] = value;
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a key/value from windows ...
|
||||
*
|
||||
* @param {string} key window id ...
|
||||
* @returns a boolean value ...
|
||||
*/
|
||||
function remove(key) {
|
||||
//
|
||||
if (!has(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
delete windows[key];
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clear all registered objects ...
|
||||
*/
|
||||
function clear() {
|
||||
windows = {};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
//
|
||||
windows: windows,
|
||||
|
||||
//
|
||||
has: has,
|
||||
get: get,
|
||||
set: set,
|
||||
keys: keys,
|
||||
count: count,
|
||||
clear: clear,
|
||||
values: values,
|
||||
remove: remove,
|
||||
}
|
||||
Reference in New Issue
Block a user