Initial Commit ...

This commit is contained in:
2026-04-17 17:04:44 +03:30
commit a986295e19
842 changed files with 97431 additions and 0 deletions
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,
}