invariant-guard 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Invariant Guard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # Invariant Guard 🛡️
2
+
3
+ A lightweight, zero-dependency runtime logic integrity engine for JavaScript. It ensures your business logic invariants are never broken silently.
4
+
5
+ ## ✨ Features
6
+
7
+ - **Runtime Integrity:** Prevents logic violations instantly.
8
+ - **Smart Rollback:** Automatically reverts data if a rule is broken.
9
+ - **Zero Overhead:** Disables completely in production mode.
10
+ - **Deep Watching:** Monitors nested objects and arrays correctly.
11
+
12
+ ## 📦 Installation
13
+
14
+ ```bash
15
+ npm install invariant-guard
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "invariant-guard",
3
+ "version": "1.0.0",
4
+ "description": "A runtime logic integrity engine for JavaScript with zero production overhead.",
5
+ "main": "src/index.js",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": "./src/index.js"
9
+ },
10
+ "scripts": {
11
+ "test": "node test.js",
12
+ "test:prod": "node test-prod.js"
13
+ },
14
+ "keywords": [
15
+ "invariant",
16
+ "validation",
17
+ "logic",
18
+ "integrity",
19
+ "proxy"
20
+ ],
21
+ "author": "",
22
+ "license": "MIT",
23
+ "files": [
24
+ "src"
25
+ ]
26
+ }
package/src/index.js ADDED
@@ -0,0 +1,41 @@
1
+ import { registry } from './registry.js';
2
+ import { createInvariant } from './observer.js';
3
+
4
+ // Default configuration
5
+ const config = {
6
+ isProduction: false, // By default, we are in DEV mode (Protections ON)
7
+ onError: null // Optional custom error handler
8
+ };
9
+
10
+ const Invariant = {
11
+ // Setup global configuration
12
+ configure: (options) => {
13
+ if (typeof options.isProduction === 'boolean') {
14
+ config.isProduction = options.isProduction;
15
+ }
16
+ if (typeof options.onError === 'function') {
17
+ config.onError = options.onError;
18
+ }
19
+ },
20
+
21
+ // Define a rule
22
+ rule: (contextName, ruleName, validatorFn) => {
23
+ // In production, we might skip registering rules to save memory,
24
+ // but keeping them is fine as long as we don't RUN them.
25
+ registry.register(contextName, ruleName, validatorFn);
26
+ },
27
+
28
+ // Watch an object
29
+ watch: (target, contextName) => {
30
+ // CRITICAL PERFORMANCE CHECK
31
+ // If we are in Production, return the raw object immediately.
32
+ // No Proxy, No Overhead.
33
+ if (config.isProduction) {
34
+ return target;
35
+ }
36
+
37
+ return createInvariant(target, contextName);
38
+ }
39
+ };
40
+
41
+ export default Invariant;
@@ -0,0 +1,43 @@
1
+ import { registry } from './registry.js';
2
+
3
+ export function createInvariant(target, contextName, root = null) {
4
+ const actualRoot = root || target;
5
+
6
+ return new Proxy(target, {
7
+ get(obj, prop) {
8
+ const value = obj[prop];
9
+ if (typeof value === 'object' && value !== null) {
10
+ return createInvariant(value, contextName, actualRoot);
11
+ }
12
+ return value;
13
+ },
14
+
15
+ set(obj, prop, value) {
16
+ const isArray = Array.isArray(obj);
17
+ const oldLength = isArray ? obj.length : 0;
18
+ const oldValue = obj[prop];
19
+
20
+ obj[prop] = value;
21
+
22
+ const rules = registry.getRules(contextName);
23
+ for (const rule of rules) {
24
+ try {
25
+ if (!rule.check(actualRoot)) {
26
+ throw new Error(`Rule "${rule.id}" failed.`);
27
+ }
28
+ } catch (err) {
29
+
30
+ obj[prop] = oldValue;
31
+
32
+ if (isArray && obj.length !== oldLength) {
33
+ obj.length = oldLength;
34
+ }
35
+
36
+ throw new Error(`[Invariant.js] Violation in "${contextName}": ${err.message}`);
37
+ }
38
+ }
39
+
40
+ return true;
41
+ }
42
+ });
43
+ }
@@ -0,0 +1,22 @@
1
+ class InvariantRegistry {
2
+ constructor() {
3
+ this.store = new Map();
4
+ }
5
+
6
+ register(contextName, ruleName, validatorFn) {
7
+ if (!this.store.has(contextName)) {
8
+ this.store.set(contextName, []);
9
+ }
10
+
11
+ this.store.get(contextName).push({
12
+ id: ruleName,
13
+ check: validatorFn
14
+ });
15
+ }
16
+
17
+ getRules(contextName) {
18
+ return this.store.get(contextName) || [];
19
+ }
20
+ }
21
+
22
+ export const registry = new InvariantRegistry();