fortifyjs-react
Version:
React integration for Nehonix FortifyJS - Secure state management with enhanced object operations
1,254 lines (1,235 loc) • 44.1 kB
JavaScript
;
var React = require('react');
var fortify2Js = require('fortify2-js');
/**
* Nehonix FortifyJS React Security Context
* Modular security context for React applications
*/
/**
* Default security configuration
*/
const DEFAULT_SECURITY_CONFIG = {
encryptionLevel: "enhanced",
defaultSensitiveKeys: [
"password",
"secret",
"token",
"key",
"auth",
"credential",
"private",
"confidential",
"ssn",
"credit",
"card",
"cvv",
"pin",
],
enableMonitoring: true,
performance: {
enableCaching: true,
cacheSize: 100,
enableLazyLoading: true,
},
memory: {
autoCleanup: true,
cleanupInterval: 30000, // 30 seconds
maxMemoryUsage: 50 * 1024 * 1024, // 50MB
},
development: {
enableDebugMode: process.env.NODE_ENV === "development",
logLevel: process.env.NODE_ENV === "development" ? "debug" : "error",
enablePerformanceMetrics: true,
},
};
/**
* Security context for managing global security settings
*/
const SecurityContext = React.createContext(null);
/**
* Hook to access security context
* @returns Security context value
* @throws Error if used outside SecurityProvider
*/
function useSecurityContext() {
const context = React.useContext(SecurityContext);
if (!context) {
throw new Error("useSecurityContext must be used within a SecurityProvider. " +
"Make sure to wrap your component tree with <SecureProvider>.");
}
return context;
}
/**
* Hook to access security configuration
* @returns Current security configuration
*/
function useSecurityConfig() {
const { config } = useSecurityContext();
return config;
}
/**
* Hook to check if a key should be treated as sensitive
* @param key - The key to check
* @returns Whether the key is sensitive
*/
function useIsSensitiveKey(key) {
const { config } = useSecurityContext();
const sensitiveKeys = config.defaultSensitiveKeys || [];
// Check exact match
if (sensitiveKeys.includes(key.toLowerCase())) {
return true;
}
// Check if key contains sensitive patterns
return sensitiveKeys.some((pattern) => key.toLowerCase().includes(pattern.toLowerCase()));
}
/**
* Hook to access security metrics
* @returns Current security metrics
*/
function useSecurityMetrics() {
const { getMetrics } = useSecurityContext();
return getMetrics();
}
/**
* Hook to control debug mode
* @returns Debug mode controls
*/
function useDebugMode() {
const { debugMode, setDebugMode } = useSecurityContext();
return {
enabled: debugMode,
enable: () => setDebugMode(true),
disable: () => setDebugMode(false),
toggle: () => setDebugMode(!debugMode),
};
}
/**
* Hook to register/unregister components for monitoring
* @param componentId - Unique component identifier
* @param metadata - Component metadata
*/
function useComponentRegistration(componentId, metadata = {}) {
const { registerComponent, unregisterComponent } = useSecurityContext();
// Register component on mount
React.useEffect(() => {
registerComponent(componentId, {
...metadata,
registeredAt: new Date(),
componentType: "react-component",
});
// Unregister on unmount
return () => {
unregisterComponent(componentId);
};
}, [componentId, registerComponent, unregisterComponent]);
}
/**
* Hook to get performance metrics for the current component
* @param componentId - Component identifier
* @returns Performance metrics
*/
function useComponentMetrics(componentId) {
useSecurityContext();
const [metrics, setMetrics] = React.useState({
renderCount: 0,
averageRenderTime: 0,
lastRenderTime: 0,
});
// Track render performance
React.useEffect(() => {
const startTime = performance.now();
return () => {
const endTime = performance.now();
const renderTime = endTime - startTime;
setMetrics((prev) => ({
renderCount: prev.renderCount + 1,
averageRenderTime: (prev.averageRenderTime * prev.renderCount + renderTime) /
(prev.renderCount + 1),
lastRenderTime: renderTime,
}));
};
});
return metrics;
}
/**
* Utility function to merge security configurations
* @param base - Base configuration
* @param override - Override configuration
* @returns Merged configuration
*/
function mergeSecurityConfig(base, override) {
return {
...base,
...override,
defaultSensitiveKeys: [
...(base.defaultSensitiveKeys || []),
...(override.defaultSensitiveKeys || []),
],
performance: {
...base.performance,
...override.performance,
},
memory: {
...base.memory,
...override.memory,
},
development: {
...base.development,
...override.development,
},
};
}
/**
* Utility function to validate security configuration
* @param config - Configuration to validate
* @throws Error if configuration is invalid
*/
function validateSecurityConfig(config) {
if (config.memory?.maxMemoryUsage && config.memory.maxMemoryUsage < 0) {
throw new Error("maxMemoryUsage must be a positive number");
}
if (config.memory?.cleanupInterval &&
config.memory.cleanupInterval < 1000) {
throw new Error("cleanupInterval must be at least 1000ms");
}
if (config.performance?.cacheSize && config.performance.cacheSize < 1) {
throw new Error("cacheSize must be at least 1");
}
const validEncryptionLevels = ["basic", "enhanced", "military"];
if (config.encryptionLevel &&
!validEncryptionLevels.includes(config.encryptionLevel)) {
throw new Error(`encryptionLevel must be one of: ${validEncryptionLevels.join(", ")}`);
}
const validLogLevels = ["none", "error", "warn", "info", "debug"];
if (config.development?.logLevel &&
!validLogLevels.includes(config.development.logLevel)) {
throw new Error(`logLevel must be one of: ${validLogLevels.join(", ")}`);
}
}
/**
* FortifyJS React useSecureState Hook
* Secure state management with automatic encryption and enhanced operations
*/
/**
* Hook for secure state management with enhanced object operations
*
* @param initialValue - Initial state value
* @param options - Configuration options
* @returns Secure state management object
*
* @example
* ```tsx
* function UserProfile() {
* const [user, setUser] = useSecureState({
* name: "John",
* email: "john@example.com",
* password: "secret123"
* }, {
* sensitiveKeys: ["password"],
* autoEncrypt: true
* });
*
* return (
* <div>
* <p>Name: {user.get("name")}</p>
* <p>Email: {user.get("email")}</p>
* // Password is automatically encrypted
* </div>
* );
* }
* ```
*/
function useSecureState(initialValue, options = {}) {
const securityContext = useSecurityContext();
const isSensitiveKey = useIsSensitiveKey;
// Configuration with defaults
const config = {
sensitiveKeys: options.sensitiveKeys || [],
autoEncrypt: options.autoEncrypt ?? true,
encryptionAlgorithm: options.encryptionAlgorithm || "AES-256-GCM",
enableMonitoring: options.enableMonitoring ?? securityContext.config.enableMonitoring,
debounceMs: options.debounceMs || 0,
...options,
};
// Create secure object with initial value
const [secureObject] = React.useState(() => {
const obj = fortify2Js.createSecureObject(initialValue);
// Set sensitive keys
const allSensitiveKeys = [
...config.sensitiveKeys,
...Object.keys(initialValue).filter((key) => isSensitiveKey(key)),
];
if (allSensitiveKeys.length > 0) {
obj.setSensitiveKeys(allSensitiveKeys);
}
return obj;
});
// Performance metrics
const metricsRef = React.useRef({
updateCount: 0,
lastUpdateTime: 0,
totalUpdateTime: 0,
});
// Force re-render when secure object changes
const [, forceUpdate] = React.useState({});
const triggerUpdate = React.useCallback(() => {
forceUpdate({});
}, []);
// Debounced update function
const debounceRef = React.useRef(null);
const debouncedUpdate = React.useCallback(() => {
if (config.debounceMs > 0) {
if (debounceRef.current) {
clearTimeout(debounceRef.current);
}
debounceRef.current = setTimeout(triggerUpdate, config.debounceMs);
}
else {
triggerUpdate();
}
}, [config.debounceMs, triggerUpdate]);
// Set up event listeners for secure object changes
React.useEffect(() => {
const handleChange = () => {
const startTime = performance.now();
// Update metrics
metricsRef.current.updateCount++;
metricsRef.current.lastUpdateTime = startTime;
// Trigger re-render
debouncedUpdate();
// Complete metrics
const endTime = performance.now();
const duration = endTime - startTime;
metricsRef.current.totalUpdateTime += duration;
// Call user event handler
if (config.validator) {
const currentValue = secureObject.toObject();
if (!config.validator(currentValue)) {
console.warn("useSecureState: Validation failed for current state");
}
}
};
// Listen to secure object events
secureObject.addEventListener("set", handleChange);
secureObject.addEventListener("delete", handleChange);
secureObject.addEventListener("clear", handleChange);
return () => {
secureObject.removeEventListener("set", handleChange);
secureObject.removeEventListener("delete", handleChange);
secureObject.removeEventListener("clear", handleChange);
if (debounceRef.current) {
clearTimeout(debounceRef.current);
}
};
}, [secureObject, debouncedUpdate, config.validator]);
// Cleanup on unmount
React.useEffect(() => {
return () => {
secureObject.destroy();
};
}, [secureObject]);
// setState function
const setState = React.useCallback((value) => {
performance.now();
try {
if (typeof value === "function") {
const currentValue = secureObject.toObject();
const newValue = value(currentValue);
// Clear and set new values
secureObject.clear();
Object.entries(newValue).forEach(([key, val]) => {
secureObject.set(key, val);
});
}
else {
// Clear and set new values
secureObject.clear();
Object.entries(value).forEach(([key, val]) => {
secureObject.set(key, val);
});
}
// Update sensitive keys if auto-detection is enabled
if (config.autoEncrypt) {
const newSensitiveKeys = Object.keys(secureObject.toObject()).filter((key) => isSensitiveKey(key));
if (newSensitiveKeys.length > 0) {
const existingSensitive = secureObject.getSensitiveKeys();
const allSensitive = [
...new Set([
...existingSensitive,
...newSensitiveKeys,
]),
];
secureObject.setSensitiveKeys(allSensitive);
}
}
}
catch (error) {
console.error("useSecureState: Error updating state:", error);
throw error;
}
}, [secureObject, config.autoEncrypt, isSensitiveKey]);
// getValue function
const getValue = React.useCallback((key) => {
return secureObject.get(key);
}, [secureObject]);
// setValue function
const setValue = React.useCallback((key, value) => {
secureObject.set(key, value);
// Auto-detect sensitive keys
if (config.autoEncrypt && isSensitiveKey(key)) {
const existingSensitive = secureObject.getSensitiveKeys();
if (!existingSensitive.includes(key)) {
secureObject.setSensitiveKeys([
...existingSensitive,
key,
]);
}
}
}, [secureObject, config.autoEncrypt, isSensitiveKey]);
// Calculate metrics
const metrics = {
updateCount: metricsRef.current.updateCount,
lastUpdateTime: metricsRef.current.lastUpdateTime,
averageUpdateTime: metricsRef.current.updateCount > 0
? metricsRef.current.totalUpdateTime /
metricsRef.current.updateCount
: 0,
};
return {
state: secureObject,
setState,
getValue,
setValue,
isEncrypted: secureObject.getSensitiveKeys().length > 0,
metrics,
};
}
/**
* FortifyJS React useSecureObject Hook
* Enhanced object operations with React integration
*/
/**
* Hook for enhanced object operations with React integration
*
* @param initialData - Initial object data or data source
* @param options - Configuration options
* @returns Enhanced object management
*
* @example
* ```tsx
* function DataProcessor() {
* const data = useSecureObject(rawData, {
* autoCleanup: true,
* enableEvents: true
* });
*
* const processedData = data.object
* .filterNonSensitive()
* .transform(value => value.toUpperCase())
* .compact();
*
* return (
* <div>
* <p>Processed {processedData.size} items</p>
* <p>Ready: {data.isReady ? "Yes" : "No"}</p>
* </div>
* );
* }
* ```
*/
function useSecureObject(initialData, options = {}) {
const securityContext = useSecurityContext();
// Configuration with defaults
const config = {
autoCleanup: options.autoCleanup ?? true,
enableEvents: options.enableEvents ?? true,
optimizationLevel: options.optimizationLevel || "balanced",
memoryStrategy: options.memoryStrategy || "balanced",
...options,
};
// State management
const [secureObject, setSecureObject] = React.useState(null);
const [isReady, setIsReady] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(true);
const [error, setError] = React.useState(null);
// Metadata tracking
const metadataRef = React.useRef({
size: 0,
sensitiveKeyCount: 0,
lastModified: new Date(),
});
// Memory management based on strategy
const memoryConfig = {
conservative: { maxSize: 1000, cleanupThreshold: 0.8 },
balanced: { maxSize: 5000, cleanupThreshold: 0.9 },
aggressive: { maxSize: 10000, cleanupThreshold: 0.95 },
}[config.memoryStrategy];
// Initialize secure object
const initializeObject = React.useCallback(async () => {
setIsLoading(true);
setError(null);
try {
let data;
if (typeof initialData === "function") {
const result = initialData();
data = result instanceof Promise ? await result : result;
}
else {
data = initialData;
}
const obj = fortify2Js.createSecureObject(data);
// Set up event listeners if enabled
if (config.enableEvents) {
const updateMetadata = () => {
metadataRef.current = {
size: obj.size,
sensitiveKeyCount: obj.getSensitiveKeys().length,
lastModified: new Date(),
};
};
obj.addEventListener("set", updateMetadata);
obj.addEventListener("delete", updateMetadata);
obj.addEventListener("clear", updateMetadata);
obj.addEventListener("filtered", updateMetadata);
}
// Apply memory management
if (obj.size > memoryConfig.maxSize) {
console.warn(`useSecureObject: Object size (${obj.size}) exceeds recommended maximum (${memoryConfig.maxSize}). ` +
"Consider using streaming operations for large datasets.");
}
setSecureObject(obj);
setIsReady(true);
// Initial metadata update
metadataRef.current = {
size: obj.size,
sensitiveKeyCount: obj.getSensitiveKeys().length,
lastModified: new Date(),
};
}
catch (err) {
const error = err instanceof Error ? err : new Error(String(err));
setError(error);
console.error("useSecureObject: Failed to initialize object:", error);
}
finally {
setIsLoading(false);
}
}, [initialData, config.enableEvents, memoryConfig.maxSize]);
// Initialize on mount
React.useEffect(() => {
initializeObject();
}, [initializeObject]);
// Cleanup on unmount
React.useEffect(() => {
return () => {
if (config.autoCleanup && secureObject) {
secureObject.destroy();
}
};
}, [config.autoCleanup, secureObject]);
// Memory monitoring
React.useEffect(() => {
if (!secureObject || !config.enableEvents)
return;
const checkMemoryUsage = () => {
const currentSize = secureObject.size;
const threshold = memoryConfig.maxSize * memoryConfig.cleanupThreshold;
if (currentSize > threshold) {
console.warn(`useSecureObject: Memory usage approaching limit. ` +
`Current: ${currentSize}, Threshold: ${threshold}`);
// Trigger garbage collection hint if available
if (typeof global !== "undefined" && global.gc) {
global.gc();
}
}
};
const interval = setInterval(checkMemoryUsage, 10000); // Check every 10 seconds
return () => clearInterval(interval);
}, [secureObject, config.enableEvents, memoryConfig]);
// Refresh function
const refresh = React.useCallback(() => {
initializeObject();
}, [initializeObject]);
// Performance monitoring
React.useEffect(() => {
if (!securityContext.config.development?.enablePerformanceMetrics)
return;
const startTime = performance.now();
return () => {
const endTime = performance.now();
const duration = endTime - startTime;
if (duration > 100) {
// Log slow operations
console.debug(`useSecureObject: Component lifecycle took ${duration.toFixed(2)}ms`);
}
};
}, [securityContext.config.development?.enablePerformanceMetrics]);
return {
object: secureObject,
refresh,
isReady,
isLoading,
error,
metadata: metadataRef.current,
};
}
/**
* Hook for creating a secure object from static data
* Simplified version of useSecureObject for static data
*
* @param data - Static object data
* @param options - Configuration options
* @returns Secure object
*/
function useStaticSecureObject(data, options = {}) {
return useSecureObject(data, { ...options, autoCleanup: true });
}
/**
* Hook for creating a secure object from async data source
* Specialized version for async data loading
*
* @param dataLoader - Async function that returns data
* @param dependencies - Dependencies that trigger reload
* @param options - Configuration options
* @returns Secure object with loading states
*/
function useAsyncSecureObject(dataLoader, dependencies = [], options = {}) {
const memoizedLoader = React.useCallback(dataLoader, dependencies);
return useSecureObject(memoizedLoader, options);
}
var jsxRuntime = {exports: {}};
var reactJsxRuntime_production = {};
/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactJsxRuntime_production;
function requireReactJsxRuntime_production () {
if (hasRequiredReactJsxRuntime_production) return reactJsxRuntime_production;
hasRequiredReactJsxRuntime_production = 1;
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
function jsxProd(type, config, maybeKey) {
var key = null;
void 0 !== maybeKey && (key = "" + maybeKey);
void 0 !== config.key && (key = "" + config.key);
if ("key" in config) {
maybeKey = {};
for (var propName in config)
"key" !== propName && (maybeKey[propName] = config[propName]);
} else maybeKey = config;
config = maybeKey.ref;
return {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key,
ref: void 0 !== config ? config : null,
props: maybeKey
};
}
reactJsxRuntime_production.Fragment = REACT_FRAGMENT_TYPE;
reactJsxRuntime_production.jsx = jsxProd;
reactJsxRuntime_production.jsxs = jsxProd;
return reactJsxRuntime_production;
}
var reactJsxRuntime_development = {};
/**
* @license React
* react-jsx-runtime.development.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var hasRequiredReactJsxRuntime_development;
function requireReactJsxRuntime_development () {
if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
hasRequiredReactJsxRuntime_development = 1;
"production" !== process.env.NODE_ENV &&
(function () {
function getComponentNameFromType(type) {
if (null == type) return null;
if ("function" === typeof type)
return type.$$typeof === REACT_CLIENT_REFERENCE
? null
: type.displayName || type.name || null;
if ("string" === typeof type) return type;
switch (type) {
case REACT_FRAGMENT_TYPE:
return "Fragment";
case REACT_PROFILER_TYPE:
return "Profiler";
case REACT_STRICT_MODE_TYPE:
return "StrictMode";
case REACT_SUSPENSE_TYPE:
return "Suspense";
case REACT_SUSPENSE_LIST_TYPE:
return "SuspenseList";
case REACT_ACTIVITY_TYPE:
return "Activity";
}
if ("object" === typeof type)
switch (
("number" === typeof type.tag &&
console.error(
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
),
type.$$typeof)
) {
case REACT_PORTAL_TYPE:
return "Portal";
case REACT_CONTEXT_TYPE:
return (type.displayName || "Context") + ".Provider";
case REACT_CONSUMER_TYPE:
return (type._context.displayName || "Context") + ".Consumer";
case REACT_FORWARD_REF_TYPE:
var innerType = type.render;
type = type.displayName;
type ||
((type = innerType.displayName || innerType.name || ""),
(type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef"));
return type;
case REACT_MEMO_TYPE:
return (
(innerType = type.displayName || null),
null !== innerType
? innerType
: getComponentNameFromType(type.type) || "Memo"
);
case REACT_LAZY_TYPE:
innerType = type._payload;
type = type._init;
try {
return getComponentNameFromType(type(innerType));
} catch (x) {}
}
return null;
}
function testStringCoercion(value) {
return "" + value;
}
function checkKeyStringCoercion(value) {
try {
testStringCoercion(value);
var JSCompiler_inline_result = !1;
} catch (e) {
JSCompiler_inline_result = !0;
}
if (JSCompiler_inline_result) {
JSCompiler_inline_result = console;
var JSCompiler_temp_const = JSCompiler_inline_result.error;
var JSCompiler_inline_result$jscomp$0 =
("function" === typeof Symbol &&
Symbol.toStringTag &&
value[Symbol.toStringTag]) ||
value.constructor.name ||
"Object";
JSCompiler_temp_const.call(
JSCompiler_inline_result,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
JSCompiler_inline_result$jscomp$0
);
return testStringCoercion(value);
}
}
function getTaskName(type) {
if (type === REACT_FRAGMENT_TYPE) return "<>";
if (
"object" === typeof type &&
null !== type &&
type.$$typeof === REACT_LAZY_TYPE
)
return "<...>";
try {
var name = getComponentNameFromType(type);
return name ? "<" + name + ">" : "<...>";
} catch (x) {
return "<...>";
}
}
function getOwner() {
var dispatcher = ReactSharedInternals.A;
return null === dispatcher ? null : dispatcher.getOwner();
}
function UnknownOwner() {
return Error("react-stack-top-frame");
}
function hasValidKey(config) {
if (hasOwnProperty.call(config, "key")) {
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
if (getter && getter.isReactWarning) return !1;
}
return void 0 !== config.key;
}
function defineKeyPropWarningGetter(props, displayName) {
function warnAboutAccessingKey() {
specialPropKeyWarningShown ||
((specialPropKeyWarningShown = !0),
console.error(
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
displayName
));
}
warnAboutAccessingKey.isReactWarning = !0;
Object.defineProperty(props, "key", {
get: warnAboutAccessingKey,
configurable: !0
});
}
function elementRefGetterWithDeprecationWarning() {
var componentName = getComponentNameFromType(this.type);
didWarnAboutElementRef[componentName] ||
((didWarnAboutElementRef[componentName] = !0),
console.error(
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
));
componentName = this.props.ref;
return void 0 !== componentName ? componentName : null;
}
function ReactElement(
type,
key,
self,
source,
owner,
props,
debugStack,
debugTask
) {
self = props.ref;
type = {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key,
props: props,
_owner: owner
};
null !== (void 0 !== self ? self : null)
? Object.defineProperty(type, "ref", {
enumerable: !1,
get: elementRefGetterWithDeprecationWarning
})
: Object.defineProperty(type, "ref", { enumerable: !1, value: null });
type._store = {};
Object.defineProperty(type._store, "validated", {
configurable: !1,
enumerable: !1,
writable: !0,
value: 0
});
Object.defineProperty(type, "_debugInfo", {
configurable: !1,
enumerable: !1,
writable: !0,
value: null
});
Object.defineProperty(type, "_debugStack", {
configurable: !1,
enumerable: !1,
writable: !0,
value: debugStack
});
Object.defineProperty(type, "_debugTask", {
configurable: !1,
enumerable: !1,
writable: !0,
value: debugTask
});
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
return type;
}
function jsxDEVImpl(
type,
config,
maybeKey,
isStaticChildren,
source,
self,
debugStack,
debugTask
) {
var children = config.children;
if (void 0 !== children)
if (isStaticChildren)
if (isArrayImpl(children)) {
for (
isStaticChildren = 0;
isStaticChildren < children.length;
isStaticChildren++
)
validateChildKeys(children[isStaticChildren]);
Object.freeze && Object.freeze(children);
} else
console.error(
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
);
else validateChildKeys(children);
if (hasOwnProperty.call(config, "key")) {
children = getComponentNameFromType(type);
var keys = Object.keys(config).filter(function (k) {
return "key" !== k;
});
isStaticChildren =
0 < keys.length
? "{key: someKey, " + keys.join(": ..., ") + ": ...}"
: "{key: someKey}";
didWarnAboutKeySpread[children + isStaticChildren] ||
((keys =
0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}"),
console.error(
'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
isStaticChildren,
children,
keys,
children
),
(didWarnAboutKeySpread[children + isStaticChildren] = !0));
}
children = null;
void 0 !== maybeKey &&
(checkKeyStringCoercion(maybeKey), (children = "" + maybeKey));
hasValidKey(config) &&
(checkKeyStringCoercion(config.key), (children = "" + config.key));
if ("key" in config) {
maybeKey = {};
for (var propName in config)
"key" !== propName && (maybeKey[propName] = config[propName]);
} else maybeKey = config;
children &&
defineKeyPropWarningGetter(
maybeKey,
"function" === typeof type
? type.displayName || type.name || "Unknown"
: type
);
return ReactElement(
type,
children,
self,
source,
getOwner(),
maybeKey,
debugStack,
debugTask
);
}
function validateChildKeys(node) {
"object" === typeof node &&
null !== node &&
node.$$typeof === REACT_ELEMENT_TYPE &&
node._store &&
(node._store.validated = 1);
}
var React$1 = React,
REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
REACT_PORTAL_TYPE = Symbol.for("react.portal"),
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
REACT_PROFILER_TYPE = Symbol.for("react.profiler");
var REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
REACT_CONTEXT_TYPE = Symbol.for("react.context"),
REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
REACT_MEMO_TYPE = Symbol.for("react.memo"),
REACT_LAZY_TYPE = Symbol.for("react.lazy"),
REACT_ACTIVITY_TYPE = Symbol.for("react.activity"),
REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"),
ReactSharedInternals =
React$1.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
hasOwnProperty = Object.prototype.hasOwnProperty,
isArrayImpl = Array.isArray,
createTask = console.createTask
? console.createTask
: function () {
return null;
};
React$1 = {
"react-stack-bottom-frame": function (callStackForError) {
return callStackForError();
}
};
var specialPropKeyWarningShown;
var didWarnAboutElementRef = {};
var unknownOwnerDebugStack = React$1["react-stack-bottom-frame"].bind(
React$1,
UnknownOwner
)();
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
var didWarnAboutKeySpread = {};
reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
reactJsxRuntime_development.jsx = function (type, config, maybeKey, source, self) {
var trackActualOwner =
1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
return jsxDEVImpl(
type,
config,
maybeKey,
!1,
source,
self,
trackActualOwner
? Error("react-stack-top-frame")
: unknownOwnerDebugStack,
trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
);
};
reactJsxRuntime_development.jsxs = function (type, config, maybeKey, source, self) {
var trackActualOwner =
1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
return jsxDEVImpl(
type,
config,
maybeKey,
!0,
source,
self,
trackActualOwner
? Error("react-stack-top-frame")
: unknownOwnerDebugStack,
trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
);
};
})();
return reactJsxRuntime_development;
}
if (process.env.NODE_ENV === 'production') {
jsxRuntime.exports = requireReactJsxRuntime_production();
} else {
jsxRuntime.exports = requireReactJsxRuntime_development();
}
var jsxRuntimeExports = jsxRuntime.exports;
/**
* Global security provider component
* Provides security context to all child components
*
* @example
* ```tsx
* function App() {
* return (
* <SecureProvider
* config={{
* encryptionLevel: "military",
* enableMonitoring: true
* }}
* >
* <UserProfile />
* <DataProcessor />
* </SecureProvider>
* );
* }
* ```
*/
const SecureProvider = ({ config: userConfig, children, fallback = null, onError, }) => {
// Merge user config with defaults
const [config, setConfig] = React.useState(() => {
try {
const mergedConfig = mergeSecurityConfig(DEFAULT_SECURITY_CONFIG, userConfig);
validateSecurityConfig(mergedConfig);
return mergedConfig;
}
catch (error) {
console.error("SecureProvider: Invalid configuration:", error);
if (onError) {
onError(error, { phase: "initialization" });
}
return DEFAULT_SECURITY_CONFIG;
}
});
// Debug mode state
const [debugMode, setDebugMode] = React.useState(config.development?.enableDebugMode ?? false);
// Component registry for monitoring
const registeredComponents = React.useRef({});
// Performance metrics
const metricsRef = React.useRef({
componentRenders: 0,
averageRenderTime: 0,
memoryUsage: 0,
operationCounts: {},
lastUpdate: new Date(),
});
// Security metrics
const securityMetricsRef = React.useRef({
totalOperations: 0,
encryptedOperations: 0,
totalOperationTime: 0,
memoryUsage: 0,
});
// Update configuration
const updateConfig = React.useCallback((newConfig) => {
try {
const mergedConfig = mergeSecurityConfig(config, newConfig);
validateSecurityConfig(mergedConfig);
setConfig(mergedConfig);
if (debugMode) {
console.debug("SecureProvider: Configuration updated", mergedConfig);
}
}
catch (error) {
console.error("SecureProvider: Failed to update configuration:", error);
if (onError) {
onError(error, { phase: "configuration-update" });
}
}
}, [config, debugMode, onError]);
// Get security metrics
const getMetrics = React.useCallback(() => {
const metrics = securityMetricsRef.current;
return {
totalOperations: metrics.totalOperations,
encryptedOperations: metrics.encryptedOperations,
averageOperationTime: metrics.totalOperations > 0
? metrics.totalOperationTime / metrics.totalOperations
: 0,
memoryUsage: metrics.memoryUsage,
};
}, []);
// Register component
const registerComponent = React.useCallback((componentId, metadata) => {
registeredComponents.current[componentId] = {
...metadata,
registeredAt: new Date(),
};
if (debugMode) {
console.debug(`SecureProvider: Registered component ${componentId}`, metadata);
}
}, [debugMode]);
// Unregister component
const unregisterComponent = React.useCallback((componentId) => {
delete registeredComponents.current[componentId];
if (debugMode) {
console.debug(`SecureProvider: Unregistered component ${componentId}`);
}
}, [debugMode]);
// Get registered components
const getRegisteredComponents = React.useCallback(() => {
return { ...registeredComponents.current };
}, []);
// Memory monitoring
React.useEffect(() => {
if (!config.memory?.autoCleanup)
return;
const interval = setInterval(() => {
// Update memory usage metrics
if (typeof performance !== "undefined" &&
performance.memory) {
const memInfo = performance.memory;
securityMetricsRef.current.memoryUsage = memInfo.usedJSHeapSize;
// Check memory threshold
const maxMemory = config.memory?.maxMemoryUsage || 50 * 1024 * 1024;
if (memInfo.usedJSHeapSize > maxMemory * 0.9) {
console.warn("SecureProvider: High memory usage detected. " +
"Consider optimizing your secure objects.");
}
}
// Clean up old component registrations
const now = new Date();
const maxAge = 5 * 60 * 1000; // 5 minutes
Object.entries(registeredComponents.current).forEach(([id, metadata]) => {
if (now.getTime() - metadata.registeredAt.getTime() >
maxAge) {
delete registeredComponents.current[id];
}
});
}, config.memory?.cleanupInterval || 30000);
return () => clearInterval(interval);
}, [config.memory]);
// Performance monitoring
React.useEffect(() => {
if (!config.development?.enablePerformanceMetrics)
return;
const startTime = performance.now();
metricsRef.current.componentRenders++;
return () => {
const endTime = performance.now();
const renderTime = endTime - startTime;
// Update average render time
const currentAvg = metricsRef.current.averageRenderTime;
const renderCount = metricsRef.current.componentRenders;
metricsRef.current.averageRenderTime =
(currentAvg * (renderCount - 1) + renderTime) / renderCount;
metricsRef.current.lastUpdate = new Date();
if (debugMode && renderTime > 16) {
// Slower than 60fps
console.debug(`SecureProvider: Slow render detected (${renderTime.toFixed(2)}ms)`);
}
};
});
// Error boundary effect
React.useEffect(() => {
const handleError = (event) => {
if (onError) {
onError(event.error, { phase: "runtime", event });
}
};
const handleUnhandledRejection = (event) => {
if (onError) {
onError(new Error(`Unhandled promise rejection: ${event.reason}`), { phase: "promise-rejection", event });
}
};
window.addEventListener("error", handleError);
window.addEventListener("unhandledrejection", handleUnhandledRejection);
return () => {
window.removeEventListener("error", handleError);
window.removeEventListener("unhandledrejection", handleUnhandledRejection);
};
}, [onError]);
// Context value
const contextValue = {
config,
updateConfig,
getMetrics,
setDebugMode,
debugMode,
registerComponent,
unregisterComponent,
getRegisteredComponents,
};
// Show fallback while initializing
if (!config) {
return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: fallback });
}
return (jsxRuntimeExports.jsx(SecurityContext.Provider, { value: contextValue, children: children }));
};
/**
* FortifyJS React Integration - Main Exports
* Complete React integration for FortifyJS
*/
// Hooks
// For CommonJS compatibility
if (typeof module !== "undefined" && module.exports) {
// Named exports
module.exports.useSecureState = useSecureState;
module.exports.useSecureObject = useSecureObject;
module.exports.useStaticSecureObject = useStaticSecureObject;
module.exports.useAsyncSecureObject = useAsyncSecureObject;
module.exports.SecureProvider = SecureProvider;
module.exports.useSecurityContext = useSecurityContext;
module.exports.useSecurityConfig = useSecurityConfig;
module.exports.useIsSensitiveKey = useIsSensitiveKey;
module.exports.useSecurityMetrics = useSecurityMetrics;
module.exports.useDebugMode = useDebugMode;
module.exports.useComponentRegistration = useComponentRegistration;
module.exports.useComponentMetrics = useComponentMetrics;
module.exports.DEFAULT_SECURITY_CONFIG = DEFAULT_SECURITY_CONFIG;
}
exports.DEFAULT_SECURITY_CONFIG = DEFAULT_SECURITY_CONFIG;
exports.SecureProvider = SecureProvider;
exports.useAsyncSecureObject = useAsyncSecureObject;
exports.useComponentMetrics = useComponentMetrics;
exports.useComponentRegistration = useComponentRegistration;
exports.useDebugMode = useDebugMode;
exports.useIsSensitiveKey = useIsSensitiveKey;
exports.useSecureObject = useSecureObject;
exports.useSecureState = useSecureState;
exports.useSecurityConfig = useSecurityConfig;
exports.useSecurityContext = useSecurityContext;
exports.useSecurityMetrics = useSecurityMetrics;
exports.useStaticSecureObject = useStaticSecureObject;
//# sourceMappingURL=index.cjs.map