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
+11
View File
@@ -0,0 +1,11 @@
# xMabsut Client Application
an application which provides Mabsut features on Platforms.
## Maintainer
Hadi Khazaee Asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+460
View File
@@ -0,0 +1,460 @@
//
//#region Required Modules ...
const url = require("url");
const path = require("path");
const { Subject } = require("rxjs");
const uuid = require("./modules/tools/x-uuid.tools");
const XLogger = require("./modules/tools/x-logger.tools");
const windowManager = require('./modules/tools/x-window.tools');
const { XElectronChannel, XElectronMessage } = require('./modules/services/x-electron.service');
const { app, shell, Tray, ipcMain, BrowserWindow, Menu } = require("electron");
//#endregion
//
//#region Prepare Required Config Data ...
//
// Set Environment ...
process.env.NODE_ENV = 'production';
//
const isDevelopment = process.env.NODE_ENV !== "production" ? true : false; // app.isPackaged;
const isMac = process.platform === "darwin" ? true : false;
//
// Show Logs ...
const showLogs = false;
//
// Show Debug Window ...
const showDebug = false;
//
// Force Window to show fullscreen ...
const isFullscreen = false;
//
// Show Window on Startup ...
const showWindowOnStartup = true;
//
const iconPath = path.join(__dirname, "www/assets/icon/favicon.png");
const trayIconPath = path.join(__dirname, "www/assets/icon/icon-16x16.png");
//#endregion
//
//#region Handle Logging ...
if (showLogs) {
XLogger.enableLogging();
} else {
XLogger.disableLogging();
}
//
console.log('XLogger State: ', XLogger.isLoggingEnable());
//#endregion
//
//#region Global Objects ...
//
let tray;
let mainUrl;
let mainWindow;
let mainWindowID;
//
const appId = uuid.generateUuid('XFrameworkElectronApp');
//#endregion
//
//#region Subscribers ...
//
const otherChannelsSubject = new Subject();
const defaultChannelSubject = new Subject();
const handShakeChannelSubject = new Subject();
//
// Register Handshake Handler ...
handShakeChannelSubject
.asObservable()
.subscribe(message => {
//
XLogger.logWarn(
XLogger.XLogMessage(
XLogger.XLogTag.Warn,
`Handshake Channel`,
[message]
)
);
});
//
// Register Default Handler ...
defaultChannelSubject
.asObservable()
.subscribe(message => {
//
XLogger.logWarn(
XLogger.XLogMessage(
XLogger.XLogTag.Warn,
`Default Channel`,
[message]
)
);
});
//
// Register Other Handler ...
otherChannelsSubject
.asObservable()
.subscribe(async message => {
//
XLogger.logWarn(
XLogger.XLogMessage(
XLogger.XLogTag.Warn,
`Other Channel`,
[message]
)
);
//
// File Service ...
if (message && message.channel === XElectronChannel.FileService) {
await handleFileServiceAction(message);
}
//
// Projects Service ...
if (message && message.channel === XElectronChannel.ProjectsService) {
await handleProjectsServiceAction(message);
}
});
//#endregion
//
//#region Creator Fuctions ...
/**
* Creat SysTray Object for using in app ...
*/
function createTray() {
//
// Create Tray Instance ...
tray = new Tray(trayIconPath);
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Tray Created ...'));
//
// Attach Event Listener to Tray Click ...
tray.on("click", () => {
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Tray Clicked ...'));
//
toggleMainWindow();
});
//
// Attach Event Listener to Tray RightClick ...
tray.on("right-click", () => {
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Tray Right Clicked ...'));
//
const contextMenu = Menu.buildFromTemplate([
{
label: "quit",
click: () => {
//
app.isClosing = true;
app.quit();
},
},
]);
//
tray.popUpContextMenu(contextMenu);
});
}
/**
* Create Main Window Instance ...
*/
function createWindow() {
//
// Create Main Window ...
mainWindow = new BrowserWindow({
icon: iconPath,
show: showWindowOnStartup,
width: isDevelopment ? 1200 : 800,
height: isDevelopment ? 800 : 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
});
//
// Handle FullScreen state if Window shown on startup ...
if (isFullscreen && showWindowOnStartup) {
mainWindow.maximize();
mainWindow.setFullScreen(true);
}
//
// Generate Main Windows UUID ...
mainWindowID = uuid.generateUuid("XFrameworkElectronWindow");
mainWindow.name = mainWindowID;
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Window ${mainWindowID} Created ...`));
//
// Fix new Window Open action ...
mainWindow.webContents.on("new-window", function (e, url) {
e.preventDefault();
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'New Window Requested ...'));
//
shell.openExternal(url);
});
//
// Handle load Main Url on Navigate for handling Navigation on Angular Apps ...
mainWindow.webContents.on("will-navigate", function (e, url) {
e.preventDefault();
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Window Will Navigate Called ...'));
//
mainWindow.loadURL(mainUrl);
});
//
// Prepare Main Url ...
mainUrl = url.format({
pathname: path.join(__dirname, "/www/index.html"),
protocol: "file",
slashes: true,
});
//
// Load Content on Main Window ...
mainWindow.loadURL(mainUrl);
//
// Remove Browser Window Default menu ...
mainWindow.removeMenu();
//
// Open Dev Tools on Development environment ...
if (showDebug) {
//
mainWindow.webContents.openDevTools();
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Window Dev Tools Opened ...'));
}
//
// Handle Window Closed ...
mainWindow.on("closed", () => {
//
mainWindow = null;
windowManager.remove(mainWindowID);
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Window ${mainWindowID} Closed ...`));
});
//
// Handle Window Close ...
mainWindow.on("close", (e) => {
//
if (!app.isClosing) {
//
e.preventDefault();
//
mainWindow.hide();
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Window ${mainWindowID} Hided ...`));
}
//
return true;
});
//
// Send Handshake Message to Angular App for Notifing id of main window ...
mainWindow.webContents.on("did-finish-load", () => {
//
// Instancing new Message for Sending ...
const handshakeMsg = new XElectronMessage(
appId,
mainWindowID,
undefined,
undefined,
XElectronChannel.Handshake,
new Date().getTime()
);
//
// Sending Handshake Message to MainWindow ...
sendMessage(handshakeMsg);
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `sending Handshake to Window ${mainWindowID} ...`));
});
//
//#region IPC Handlers ...
//
// Register Event Handler for HandShake ...
ipcMain.on(XElectronChannel.Handshake, (event, message) => {
//
if (!message || !message.sender) {
return;
}
//
const windowID = message.sender;
windowManager.set(windowID, mainWindow);
//
handShakeChannelSubject.next(message);
});
//
// Register Event Handler for Message ...
ipcMain.on(XElectronChannel.Default, (event, message) => {
defaultChannelSubject.next(message);
});
//
const channels = Object.assign({}, XElectronChannel);
delete channels.Default;
delete channels.Handshake;
//
Object.keys(channels).forEach(channel => {
//
// Register Event Handler for Message on other Channel ...
ipcMain.on(channels[channel], (event, message) => {
otherChannelsSubject.next(message);
});
});
//#endregion
}
/**
* Toggle Show/Hide Main Window ...
*/
function toggleMainWindow() {
//
if (!mainWindow) {
return;
}
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Toggle Window ...`));
//
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
//
if (isFullscreen) {
mainWindow.maximize();
mainWindow.setFullScreen(true);
}
mainWindow.show();
}
}
//#endregion
//
//#region Event Emitters ...
/**
* attach event to call when it's ready, to app object ...
*/
app.whenReady().then(() => {
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `App Ready ...`));
//
createTray();
createWindow();
});
/**
* attach event to call when all application Windows closed, to app object ...
*/
app.on("window-all-closed", () => {
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `All Windows Closed ...`));
//
if (!isMac) {
app.quit();
}
});
/**
* attach event to call when application activated, to app object ...
*/
app.on("activate", () => {
//
XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `App Activated ...`));
//
if (!mainWindow) {
createWindow();
}
});
//#endregion
//
//#region Window Comminucations ...
/**
* send a message to specified window ...
*
* @param {XElectronMessageDto} message the message which required to send ...
*/
function sendMessage(message) {
//
if (!message) {
return;
}
//
if (!message.sender) {
message.sender = appId;
}
//
if (!message.reciever) {
message.reciever = mainWindowID;
}
//
let destWindow = undefined;
if (windowManager.count() === 0) {
destWindow = mainWindow;
} else {
destWindow = windowManager.get(message.reciever);
}
//
if (!destWindow) {
//
const errorMessage = 'Dest Window not found ...';
XLogger.logError(XLogger.XLogMessage(XLogger.XLogTag.Error, errorMessage))
throw errorMessage;
}
//
// Sending Message to Window ...
destWindow.webContents.send(
message.channel,
JSON.stringify(message)
);
}
//#endregion
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,
}
+37
View File
@@ -0,0 +1,37 @@
{
"name": "x-mabsut-client",
"version": "1.0.0",
"description": "Mabsut CLient application",
"homepage": "https://mabsut.ir",
"author": {
"name": "Hadi Khazaee Asl",
"email": "hadi_khazaee_asl@yahoo.com",
"url": "https://saherelm.ir"
},
"keywords": [
"x-mabsut",
"x-framework",
"saherelm"
],
"scripts": {
"true": "",
"startElectron": "electron .",
"rmWWW": "shx --silent rm -rf ./www",
"prepareElectron": "npm run rmWWW && shx --silent cp -r ../../dist/xClient ./www",
"runElectron": "npm run rmWWW && cd .. && cd .. && npm run build && cd platforms/electron && npm run prepareElectron && npm run startElectron",
"runProdElectron": "cd .. && cd .. && npm run buildProd && cd platforms/electron && npm run prepareElectron && npm run startElectron",
"buildElectronWin32": "cd .. && cd .. && npm run buildProd && cd platforms/electron && npm run prepareElectron && electron-packager . --platform=win32 --arch=ia32 --icon=www/assets/icon/favicon.ico --overwrite --prune=true --out=dist",
"buildElectronWin64": "cd .. && cd .. && npm run buildProd && cd platforms/electron && npm run prepareElectron && electron-packager . --platform=win32 --arch=x64 --icon=www/assets/icon/favicon.ico --overwrite --prune=true --out=dist",
"buildElectronMac64": "cd .. && cd .. && npm run buildProd && cd platforms/electron && npm run prepareElectron && electron-packager . --platform=darwin --arch=x64 --icon=www/assets/icon/favicon.icns --overwrite --prune=true --out=dist",
"buildElectronLinux64": "cd .. && cd .. && npm run buildProd && cd platforms/electron && npm run prepareElectron && electron-packager . --platform=linux --arch=x64 --icon=www/assets/icon/favicon.png --overwrite --prune=true --out=dist"
},
"devDependencies": {
"electron-packager": "^15.3.0",
"uuid": "^8.3.2",
"shx": "^0.3.3"
},
"dependencies": {
"electron": "^13.1.7"
},
"main": "app.electron.js"
}