fortify2-js
Version:
MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.
332 lines (329 loc) • 10.3 kB
JavaScript
;
/***************************************************************************
* FortifyJS - Secure Array Metadata Manager
*
* This file contains the metadata management system for SecureArray
*
* @author Nehonix
*
* @license MIT
*
* Copyright (c) 2025 Nehonix. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***************************************************************************** */
/**
* Manages metadata for SecureArray elements
*/
class ArrayMetadataManager {
constructor() {
this.metadata = new Map();
}
/**
* Updates metadata for an element at the specified index
*/
update(index, type, isSecure, accessed = false) {
const existing = this.metadata.get(index);
const now = new Date();
if (existing) {
existing.type = type;
existing.isSecure = isSecure;
if (accessed) {
existing.lastAccessed = now;
existing.accessCount++;
}
}
else {
this.metadata.set(index, {
type,
isSecure,
created: now,
lastAccessed: now,
accessCount: accessed ? 1 : 0,
index,
});
}
}
/**
* Gets metadata for an element at the specified index
*/
get(index) {
return this.metadata.get(index);
}
/**
* Checks if metadata exists for an element at the specified index
*/
has(index) {
return this.metadata.has(index);
}
/**
* Deletes metadata for an element at the specified index
*/
delete(index) {
return this.metadata.delete(index);
}
/**
* Gets all metadata
*/
getAll() {
return new Map(this.metadata);
}
/**
* Clears all metadata
*/
clear() {
this.metadata.clear();
}
/**
* Gets statistics about the metadata
*/
getStats() {
if (this.metadata.size === 0) {
return {
totalElements: 0,
secureElements: 0,
totalAccesses: 0,
averageAccessCount: 0,
oldestElement: null,
newestElement: null,
};
}
let secureElements = 0;
let totalAccesses = 0;
let oldestElement = null;
let newestElement = null;
for (const metadata of this.metadata.values()) {
if (metadata.isSecure) {
secureElements++;
}
totalAccesses += metadata.accessCount;
if (!oldestElement || metadata.created < oldestElement) {
oldestElement = metadata.created;
}
if (!newestElement || metadata.created > newestElement) {
newestElement = metadata.created;
}
}
return {
totalElements: this.metadata.size,
secureElements,
totalAccesses,
averageAccessCount: totalAccesses / this.metadata.size,
oldestElement,
newestElement,
};
}
/**
* Compacts metadata by removing entries for indices that no longer exist
*/
compact(maxIndex) {
const toDelete = [];
for (const index of this.metadata.keys()) {
if (index >= maxIndex) {
toDelete.push(index);
}
}
for (const index of toDelete) {
this.metadata.delete(index);
}
}
/**
* Shifts metadata indices when elements are inserted or removed
*/
shiftIndices(startIndex, shift) {
const newMetadata = new Map();
for (const [index, metadata] of this.metadata.entries()) {
if (index >= startIndex) {
const newIndex = index + shift;
if (newIndex >= 0) {
metadata.index = newIndex;
newMetadata.set(newIndex, metadata);
}
}
else {
newMetadata.set(index, metadata);
}
}
this.metadata = newMetadata;
}
/**
* Gets metadata for secure elements only
*/
getSecureElementsMetadata() {
const secureMetadata = new Map();
for (const [index, metadata] of this.metadata.entries()) {
if (metadata.isSecure) {
secureMetadata.set(index, metadata);
}
}
return secureMetadata;
}
/**
* Gets elements that haven't been accessed recently
*/
getStaleElements(maxAge) {
const now = new Date();
const staleIndices = [];
for (const [index, metadata] of this.metadata.entries()) {
const age = now.getTime() - metadata.lastAccessed.getTime();
if (age > maxAge) {
staleIndices.push(index);
}
}
return staleIndices;
}
/**
* Gets the most frequently accessed elements
*/
getMostAccessedElements(limit = 10) {
const elements = Array.from(this.metadata.entries())
.map(([index, metadata]) => ({
index,
accessCount: metadata.accessCount,
}))
.sort((a, b) => b.accessCount - a.accessCount)
.slice(0, limit);
return elements;
}
/**
* Gets elements by type
*/
getElementsByType(type) {
const indices = [];
for (const [index, metadata] of this.metadata.entries()) {
if (metadata.type === type) {
indices.push(index);
}
}
return indices;
}
/**
* Validates metadata integrity
*/
validateIntegrity() {
const errors = [];
const warnings = [];
// Check for negative indices
for (const index of this.metadata.keys()) {
if (index < 0) {
errors.push(`Invalid negative index: ${index}`);
}
}
// Check for metadata consistency
for (const [index, metadata] of this.metadata.entries()) {
if (metadata.index !== index) {
errors.push(`Index mismatch: metadata.index=${metadata.index}, key=${index}`);
}
if (metadata.accessCount < 0) {
errors.push(`Invalid access count: ${metadata.accessCount} at index ${index}`);
}
if (metadata.created > new Date()) {
warnings.push(`Future creation date at index ${index}`);
}
if (metadata.lastAccessed < metadata.created) {
warnings.push(`Last accessed before creation at index ${index}`);
}
}
return {
isValid: errors.length === 0,
errors,
warnings,
};
}
/**
* Exports metadata to a serializable format
*/
export() {
return Array.from(this.metadata.entries());
}
/**
* Imports metadata from a serializable format
*/
import(data) {
this.metadata.clear();
for (const [index, metadata] of data) {
this.metadata.set(index, {
...metadata,
created: new Date(metadata.created),
lastAccessed: new Date(metadata.lastAccessed),
});
}
}
/**
* Gets the size of the metadata map
*/
size() {
return this.metadata.size;
}
/**
* Gets all metadata (alias for getAll)
*/
getAllMetadata() {
return this.getAll();
}
/**
* Handles splice operations on metadata
*/
splice(start, deleteCount, insertCount) {
const newMetadata = new Map();
// Copy metadata before the splice point
for (const [index, metadata] of this.metadata.entries()) {
if (index < start) {
newMetadata.set(index, metadata);
}
else if (index >= start + deleteCount) {
// Shift indices after the splice point
const newIndex = index - deleteCount + insertCount;
metadata.index = newIndex;
newMetadata.set(newIndex, metadata);
}
// Skip metadata in the deleted range
}
this.metadata = newMetadata;
}
/**
* Reverses the metadata indices
*/
reverse(length) {
const newMetadata = new Map();
for (const [index, metadata] of this.metadata.entries()) {
const newIndex = length - 1 - index;
metadata.index = newIndex;
newMetadata.set(newIndex, metadata);
}
this.metadata = newMetadata;
}
/**
* Reorders metadata based on new index mapping
*/
reorder(newIndices) {
const newMetadata = new Map();
for (let i = 0; i < newIndices.length; i++) {
const oldIndex = newIndices[i];
const metadata = this.metadata.get(oldIndex);
if (metadata) {
metadata.index = i;
newMetadata.set(i, metadata);
}
}
this.metadata = newMetadata;
}
}
exports.ArrayMetadataManager = ArrayMetadataManager;
//# sourceMappingURL=metadata-manager.js.map