Files
2026-04-17 17:04:44 +03:30

423 lines
9.5 KiB
JavaScript

//
//#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,
}