@bernierllc/nevar-types 0.0.1 → 0.1.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/.eslintrc.js +29 -0
- package/LICENSE +5 -0
- package/README.md +128 -43
- package/__tests__/errors.test.ts +189 -0
- package/__tests__/type-guards.test.ts +152 -0
- package/dist/actions.d.ts +71 -0
- package/dist/actions.js +9 -0
- package/dist/conditions.d.ts +24 -0
- package/dist/conditions.js +35 -0
- package/dist/config.d.ts +64 -0
- package/dist/config.js +9 -0
- package/dist/context.d.ts +8 -0
- package/dist/context.js +9 -0
- package/dist/errors.d.ts +59 -0
- package/dist/errors.js +95 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +23 -0
- package/dist/models.d.ts +56 -0
- package/dist/models.js +9 -0
- package/dist/operators.d.ts +24 -0
- package/dist/operators.js +9 -0
- package/dist/results.d.ts +79 -0
- package/dist/results.js +9 -0
- package/dist/storage.d.ts +100 -0
- package/dist/storage.js +9 -0
- package/dist/triggers.d.ts +11 -0
- package/dist/triggers.js +9 -0
- package/jest.config.cjs +29 -0
- package/package.json +35 -7
- package/proof-coverage.json +41 -0
- package/src/actions.ts +91 -0
- package/src/conditions.ts +55 -0
- package/src/config.ts +78 -0
- package/src/context.ts +16 -0
- package/src/errors.ts +102 -0
- package/src/index.ts +79 -0
- package/src/models.ts +68 -0
- package/src/operators.ts +33 -0
- package/src/results.ts +91 -0
- package/src/storage.ts +118 -0
- package/src/triggers.ts +19 -0
- package/tsconfig.json +22 -0
package/jest.config.cjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
preset: 'ts-jest',
|
|
11
|
+
testEnvironment: '<rootDir>/../../../jest-environment-node-fixed.cjs',
|
|
12
|
+
roots: ['<rootDir>/__tests__'],
|
|
13
|
+
testMatch: ['**/*.test.ts'],
|
|
14
|
+
collectCoverageFrom: [
|
|
15
|
+
'src/**/*.ts',
|
|
16
|
+
'!src/**/*.d.ts',
|
|
17
|
+
'!src/index.ts'
|
|
18
|
+
],
|
|
19
|
+
coverageThreshold: {
|
|
20
|
+
global: {
|
|
21
|
+
branches: 90,
|
|
22
|
+
functions: 90,
|
|
23
|
+
lines: 90,
|
|
24
|
+
statements: 90
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
coverageDirectory: 'coverage',
|
|
28
|
+
verbose: true
|
|
29
|
+
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bernierllc/nevar-types",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared type definitions, interfaces, error classes, and type guards for the Nevar rules engine suite",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
5
7
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
"nevar",
|
|
9
|
+
"rules-engine",
|
|
10
|
+
"types",
|
|
11
|
+
"type-definitions",
|
|
12
|
+
"error-classes"
|
|
13
|
+
],
|
|
14
|
+
"author": "Bernier LLC",
|
|
15
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/jest": "^29.5.0",
|
|
18
|
+
"@types/node": "^20.0.0",
|
|
19
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
20
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
21
|
+
"eslint": "^8.0.0",
|
|
22
|
+
"jest": "^29.5.0",
|
|
23
|
+
"ts-jest": "^29.1.0",
|
|
24
|
+
"typescript": "^5.0.0"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public",
|
|
28
|
+
"registry": "https://registry.npmjs.org/"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"test": "jest",
|
|
33
|
+
"test:run": "jest",
|
|
34
|
+
"test:coverage": "jest --coverage",
|
|
35
|
+
"lint": "eslint src __tests__ --ext .ts",
|
|
36
|
+
"clean": "rm -rf dist"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"package": "@bernierllc/nevar-types",
|
|
3
|
+
"coverageType": "transitive",
|
|
4
|
+
"proofApp": "proof/nevar-engine",
|
|
5
|
+
"transitiveThrough": "@bernierllc/nevar-engine",
|
|
6
|
+
"lastVerified": "2026-03-27",
|
|
7
|
+
"lastVerifiedVersion": "0.1.0",
|
|
8
|
+
"features": {
|
|
9
|
+
"NevarConfig": { "status": "covered", "scenario": "registration" },
|
|
10
|
+
"Rule": { "status": "covered", "scenario": "rule-crud" },
|
|
11
|
+
"RuleGroup": { "status": "covered", "scenario": "rule-crud" },
|
|
12
|
+
"ConditionGroup": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
13
|
+
"ActionDefinition": { "status": "covered", "scenario": "rule-crud" },
|
|
14
|
+
"ActionHandlerDefinition": { "status": "covered", "scenario": "registration" },
|
|
15
|
+
"ActionResult": { "status": "covered", "scenario": "action-execution" },
|
|
16
|
+
"ActionIntent": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
17
|
+
"DeferredTrigger": { "status": "covered", "scenario": "action-execution" },
|
|
18
|
+
"EmitResult": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
19
|
+
"PreviewResult": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
20
|
+
"TriggerDefinition": { "status": "covered", "scenario": "registration" },
|
|
21
|
+
"OperatorDefinition": { "status": "covered", "scenario": "registration" },
|
|
22
|
+
"OperatorInfo": { "status": "covered", "scenario": "discovery" },
|
|
23
|
+
"ExecutionLogEntry": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
24
|
+
"NevarStorageAdapter": { "status": "covered", "scenario": "storage-conformance" },
|
|
25
|
+
"CircuitBreakerConfig": { "status": "covered", "scenario": "safety" },
|
|
26
|
+
"LoopHandle": { "status": "covered", "scenario": "safety" },
|
|
27
|
+
"isConditionGroup": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
28
|
+
"isCondition": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
29
|
+
"NevarValidationError": { "status": "covered", "scenario": "rule-crud" },
|
|
30
|
+
"NevarStorageError": { "status": "covered", "scenario": "rule-crud" },
|
|
31
|
+
"EvaluationTrace": { "status": "covered", "scenario": "evaluation-pipeline" },
|
|
32
|
+
"PaginatedResult": { "status": "covered", "scenario": "storage-conformance" },
|
|
33
|
+
"GroupFilters": { "status": "covered", "scenario": "storage-conformance" },
|
|
34
|
+
"RuleFilters": { "status": "covered", "scenario": "storage-conformance" },
|
|
35
|
+
"LogFilters": { "status": "covered", "scenario": "storage-conformance" },
|
|
36
|
+
"ActionFailureMode": { "status": "covered", "scenario": "registration" },
|
|
37
|
+
"ActionRetryConfig": { "status": "covered", "scenario": "action-retry" },
|
|
38
|
+
"LoopConfig": { "status": "uncovered", "reason": "type exists but engine constructor does not use it in current implementation" },
|
|
39
|
+
"AuditLoggerConfig": { "status": "uncovered", "reason": "nevar-audit-logger not exercised in proof app" }
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/actions.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for retrying a failed action with exponential backoff.
|
|
11
|
+
*/
|
|
12
|
+
export interface ActionRetryConfig {
|
|
13
|
+
maxAttempts: number;
|
|
14
|
+
backoffMs: number;
|
|
15
|
+
backoffMultiplier: number;
|
|
16
|
+
maxBackoffMs: number;
|
|
17
|
+
retryableErrors?: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Defines an action to execute when a rule matches.
|
|
22
|
+
*/
|
|
23
|
+
export interface ActionDefinition {
|
|
24
|
+
actionType: string;
|
|
25
|
+
config: Record<string, unknown>;
|
|
26
|
+
executionOrder: number;
|
|
27
|
+
retry?: ActionRetryConfig;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* An intent represents a planned action derived from a matched rule.
|
|
32
|
+
*/
|
|
33
|
+
export interface ActionIntent {
|
|
34
|
+
actionType: string;
|
|
35
|
+
config: Record<string, unknown>;
|
|
36
|
+
ruleId: string;
|
|
37
|
+
ruleName: string;
|
|
38
|
+
retry?: ActionRetryConfig;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A trigger that should be fired as a result of an action execution.
|
|
43
|
+
*/
|
|
44
|
+
export interface DeferredTrigger {
|
|
45
|
+
triggerKey: string;
|
|
46
|
+
payload: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The result of executing a single action.
|
|
51
|
+
*/
|
|
52
|
+
export interface ActionResult {
|
|
53
|
+
intent: ActionIntent;
|
|
54
|
+
status: 'success' | 'error';
|
|
55
|
+
output: Record<string, unknown>;
|
|
56
|
+
deferredTriggers?: DeferredTrigger[];
|
|
57
|
+
durationMs: number;
|
|
58
|
+
attempts: number;
|
|
59
|
+
lastError?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Controls how action failures are handled within a rule's action list.
|
|
64
|
+
*/
|
|
65
|
+
export type ActionFailureMode = 'fail-fast' | 'best-effort';
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Defines an action handler that can be registered with the engine.
|
|
69
|
+
* Includes the handler function, metadata for discovery, and a config schema.
|
|
70
|
+
*/
|
|
71
|
+
export interface ActionHandlerDefinition {
|
|
72
|
+
label: string;
|
|
73
|
+
category: string;
|
|
74
|
+
canDefer: boolean;
|
|
75
|
+
configSchema: unknown;
|
|
76
|
+
handler: (
|
|
77
|
+
config: Record<string, unknown>,
|
|
78
|
+
context: Record<string, unknown>,
|
|
79
|
+
priorResults: ActionResult[]
|
|
80
|
+
) => Promise<Record<string, unknown>>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The aggregate result of executing a set of action intents.
|
|
85
|
+
*/
|
|
86
|
+
export interface ExecutionResult {
|
|
87
|
+
results: ActionResult[];
|
|
88
|
+
deferredTriggers: DeferredTrigger[];
|
|
89
|
+
durationMs: number;
|
|
90
|
+
}
|
|
91
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A group of conditions combined with a logical operator.
|
|
11
|
+
* NOT groups evaluate children as AND, then negate the result.
|
|
12
|
+
*/
|
|
13
|
+
export interface ConditionGroup {
|
|
14
|
+
operator: 'AND' | 'OR' | 'NOT';
|
|
15
|
+
conditions: (ConditionGroup | Condition)[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A single condition that compares a field value using an operator.
|
|
20
|
+
*/
|
|
21
|
+
export interface Condition {
|
|
22
|
+
field: string;
|
|
23
|
+
op: string;
|
|
24
|
+
value: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Type guard: checks whether the given value is a ConditionGroup.
|
|
29
|
+
*/
|
|
30
|
+
export function isConditionGroup(value: unknown): value is ConditionGroup {
|
|
31
|
+
if (value === null || value === undefined || typeof value !== 'object') {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const obj = value as Record<string, unknown>;
|
|
35
|
+
return (
|
|
36
|
+
typeof obj.operator === 'string' &&
|
|
37
|
+
(obj.operator === 'AND' || obj.operator === 'OR' || obj.operator === 'NOT') &&
|
|
38
|
+
Array.isArray(obj.conditions)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Type guard: checks whether the given value is a Condition.
|
|
44
|
+
*/
|
|
45
|
+
export function isCondition(value: unknown): value is Condition {
|
|
46
|
+
if (value === null || value === undefined || typeof value !== 'object') {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const obj = value as Record<string, unknown>;
|
|
50
|
+
return (
|
|
51
|
+
typeof obj.field === 'string' &&
|
|
52
|
+
typeof obj.op === 'string' &&
|
|
53
|
+
'value' in obj
|
|
54
|
+
);
|
|
55
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { LogLevel } from './models';
|
|
10
|
+
import { ActionFailureMode } from './actions';
|
|
11
|
+
import { NevarStorageAdapter } from './storage';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for the circuit breaker that prevents cascading failures.
|
|
15
|
+
*/
|
|
16
|
+
export interface CircuitBreakerConfig {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
maxFailures?: number;
|
|
19
|
+
resetTimeMs?: number;
|
|
20
|
+
halfOpenMaxAttempts?: number;
|
|
21
|
+
maxCascadeDepth?: number;
|
|
22
|
+
maxActionsPerChain?: number;
|
|
23
|
+
maxChainDurationMs?: number;
|
|
24
|
+
maxConcurrentChains?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Configuration for loop detection and prevention.
|
|
29
|
+
*/
|
|
30
|
+
export interface LoopConfig {
|
|
31
|
+
maxDepth?: number;
|
|
32
|
+
maxExecutionsPerTrigger?: number;
|
|
33
|
+
windowMs?: number;
|
|
34
|
+
allowInfiniteLoops?: boolean;
|
|
35
|
+
maxConcurrentLoops?: number;
|
|
36
|
+
heartbeatIntervalMs?: number;
|
|
37
|
+
maxMissedHeartbeats?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Configuration for the audit logger.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* Override structure for per-rule, per-trigger, and per-action log levels.
|
|
45
|
+
*/
|
|
46
|
+
export interface AuditLoggerOverrides {
|
|
47
|
+
byRule?: Record<string, LogLevel>;
|
|
48
|
+
byTrigger?: Record<string, LogLevel>;
|
|
49
|
+
byAction?: Record<string, LogLevel>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface AuditLoggerConfig {
|
|
53
|
+
enabled?: boolean;
|
|
54
|
+
logLevel?: LogLevel;
|
|
55
|
+
retentionDays?: number;
|
|
56
|
+
defaultLevel?: LogLevel;
|
|
57
|
+
overrides?: AuditLoggerOverrides;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Strategy for seeding initial rules into storage.
|
|
62
|
+
*/
|
|
63
|
+
export type SeedStrategy = 'skip-existing' | 'overwrite' | 'error-on-conflict' | 'skip_existing' | 'update_existing' | 'replace_all';
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Top-level configuration for the Nevar engine.
|
|
67
|
+
*/
|
|
68
|
+
export interface NevarConfig {
|
|
69
|
+
storage: NevarStorageAdapter;
|
|
70
|
+
defaultGroupId?: string;
|
|
71
|
+
logLevel?: LogLevel;
|
|
72
|
+
failureMode?: ActionFailureMode;
|
|
73
|
+
actionFailureMode?: ActionFailureMode;
|
|
74
|
+
circuitBreaker?: CircuitBreakerConfig;
|
|
75
|
+
loop?: LoopConfig;
|
|
76
|
+
auditLogger?: AuditLoggerConfig;
|
|
77
|
+
seedStrategy?: SeedStrategy;
|
|
78
|
+
}
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Defines a context provider that enriches trigger payloads with additional data.
|
|
11
|
+
*/
|
|
12
|
+
export interface ContextProviderDefinition {
|
|
13
|
+
key: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
resolve: (payload: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
16
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Options for constructing a NevarError.
|
|
11
|
+
*/
|
|
12
|
+
export interface NevarErrorOptions {
|
|
13
|
+
cause?: Error;
|
|
14
|
+
code?: string;
|
|
15
|
+
context?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Base error class for all Nevar errors.
|
|
20
|
+
* Follows ES2022 Error.cause pattern for error chain propagation.
|
|
21
|
+
*/
|
|
22
|
+
export class NevarError extends Error {
|
|
23
|
+
readonly code: string;
|
|
24
|
+
readonly context?: Record<string, unknown>;
|
|
25
|
+
|
|
26
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
27
|
+
super(message, { cause: options?.cause });
|
|
28
|
+
this.name = 'NevarError';
|
|
29
|
+
this.code = options?.code ?? 'NEVAR_ERROR';
|
|
30
|
+
this.context = options?.context;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Thrown when a trigger fails to fire or is invalid.
|
|
36
|
+
*/
|
|
37
|
+
export class NevarTriggerError extends NevarError {
|
|
38
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
39
|
+
super(message, { ...options, code: options?.code ?? 'NEVAR_TRIGGER_ERROR' });
|
|
40
|
+
this.name = 'NevarTriggerError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Thrown when condition evaluation fails.
|
|
46
|
+
*/
|
|
47
|
+
export class NevarEvaluationError extends NevarError {
|
|
48
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
49
|
+
super(message, { ...options, code: options?.code ?? 'NEVAR_EVALUATION_ERROR' });
|
|
50
|
+
this.name = 'NevarEvaluationError';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Thrown when an action fails to execute.
|
|
56
|
+
*/
|
|
57
|
+
export class NevarActionError extends NevarError {
|
|
58
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
59
|
+
super(message, { ...options, code: options?.code ?? 'NEVAR_ACTION_ERROR' });
|
|
60
|
+
this.name = 'NevarActionError';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Thrown when the circuit breaker trips due to too many failures.
|
|
66
|
+
*/
|
|
67
|
+
export class NevarCircuitBreakerError extends NevarError {
|
|
68
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
69
|
+
super(message, { ...options, code: options?.code ?? 'NEVAR_CIRCUIT_BREAKER_ERROR' });
|
|
70
|
+
this.name = 'NevarCircuitBreakerError';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Thrown when a loop is detected in the evaluation chain.
|
|
76
|
+
*/
|
|
77
|
+
export class NevarLoopError extends NevarError {
|
|
78
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
79
|
+
super(message, { ...options, code: options?.code ?? 'NEVAR_LOOP_ERROR' });
|
|
80
|
+
this.name = 'NevarLoopError';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Thrown when a storage operation fails.
|
|
86
|
+
*/
|
|
87
|
+
export class NevarStorageError extends NevarError {
|
|
88
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
89
|
+
super(message, { ...options, code: options?.code ?? 'NEVAR_STORAGE_ERROR' });
|
|
90
|
+
this.name = 'NevarStorageError';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Thrown when input validation fails.
|
|
96
|
+
*/
|
|
97
|
+
export class NevarValidationError extends NevarError {
|
|
98
|
+
constructor(message: string, options?: NevarErrorOptions) {
|
|
99
|
+
super(message, { ...options, code: options?.code ?? 'NEVAR_VALIDATION_ERROR' });
|
|
100
|
+
this.name = 'NevarValidationError';
|
|
101
|
+
}
|
|
102
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Models
|
|
10
|
+
export type { LogLevel, RuleGroup, Rule, EvaluationTrace } from './models';
|
|
11
|
+
|
|
12
|
+
// Conditions
|
|
13
|
+
export type { ConditionGroup, Condition } from './conditions';
|
|
14
|
+
export { isConditionGroup, isCondition } from './conditions';
|
|
15
|
+
|
|
16
|
+
// Actions
|
|
17
|
+
export type {
|
|
18
|
+
ActionRetryConfig,
|
|
19
|
+
ActionDefinition,
|
|
20
|
+
ActionIntent,
|
|
21
|
+
DeferredTrigger,
|
|
22
|
+
ActionResult,
|
|
23
|
+
ActionFailureMode,
|
|
24
|
+
ActionHandlerDefinition,
|
|
25
|
+
ExecutionResult,
|
|
26
|
+
} from './actions';
|
|
27
|
+
|
|
28
|
+
// Triggers
|
|
29
|
+
export type { TriggerDefinition } from './triggers';
|
|
30
|
+
|
|
31
|
+
// Context
|
|
32
|
+
export type { ContextProviderDefinition } from './context';
|
|
33
|
+
|
|
34
|
+
// Operators
|
|
35
|
+
export type { OperatorDefinition, OperatorInfo } from './operators';
|
|
36
|
+
|
|
37
|
+
// Storage
|
|
38
|
+
export type {
|
|
39
|
+
GroupFilters,
|
|
40
|
+
RuleFilters,
|
|
41
|
+
LogFilters,
|
|
42
|
+
PaginatedResult,
|
|
43
|
+
ExecutionLogEntry,
|
|
44
|
+
NevarStorageAdapter,
|
|
45
|
+
} from './storage';
|
|
46
|
+
|
|
47
|
+
// Config
|
|
48
|
+
export type {
|
|
49
|
+
CircuitBreakerConfig,
|
|
50
|
+
LoopConfig,
|
|
51
|
+
AuditLoggerConfig,
|
|
52
|
+
AuditLoggerOverrides,
|
|
53
|
+
SeedStrategy,
|
|
54
|
+
NevarConfig,
|
|
55
|
+
} from './config';
|
|
56
|
+
|
|
57
|
+
// Results
|
|
58
|
+
export type {
|
|
59
|
+
EvaluationResult,
|
|
60
|
+
EmitResult,
|
|
61
|
+
PreviewResult,
|
|
62
|
+
MatchedRule,
|
|
63
|
+
LoopHandle,
|
|
64
|
+
LoopAnalysis,
|
|
65
|
+
DetectedLoop,
|
|
66
|
+
} from './results';
|
|
67
|
+
|
|
68
|
+
// Errors
|
|
69
|
+
export {
|
|
70
|
+
NevarError,
|
|
71
|
+
NevarTriggerError,
|
|
72
|
+
NevarEvaluationError,
|
|
73
|
+
NevarActionError,
|
|
74
|
+
NevarCircuitBreakerError,
|
|
75
|
+
NevarLoopError,
|
|
76
|
+
NevarStorageError,
|
|
77
|
+
NevarValidationError,
|
|
78
|
+
} from './errors';
|
|
79
|
+
export type { NevarErrorOptions } from './errors';
|
package/src/models.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { ConditionGroup } from './conditions';
|
|
10
|
+
import { ActionDefinition } from './actions';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Log level for rule evaluation and execution tracing.
|
|
14
|
+
*/
|
|
15
|
+
export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'all' | 'none' | 'matches_only' | 'errors_only';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A rule group organizes rules under a shared context (e.g., tenant, environment).
|
|
19
|
+
*/
|
|
20
|
+
export interface RuleGroup {
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
slug: string;
|
|
24
|
+
isActive?: boolean;
|
|
25
|
+
isDefault: boolean;
|
|
26
|
+
rules?: Rule[];
|
|
27
|
+
metadata: Record<string, unknown>;
|
|
28
|
+
createdAt: Date;
|
|
29
|
+
updatedAt: Date;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A rule defines conditions that, when matched against a trigger, produce actions.
|
|
34
|
+
*/
|
|
35
|
+
export interface Rule {
|
|
36
|
+
id: string;
|
|
37
|
+
groupId: string;
|
|
38
|
+
name: string;
|
|
39
|
+
slug: string;
|
|
40
|
+
triggerType: string;
|
|
41
|
+
conditions: ConditionGroup;
|
|
42
|
+
actions: ActionDefinition[];
|
|
43
|
+
executionOrder: number;
|
|
44
|
+
isActive: boolean;
|
|
45
|
+
stopOnMatch: boolean;
|
|
46
|
+
allowLoop: boolean;
|
|
47
|
+
logLevel: LogLevel;
|
|
48
|
+
metadata: Record<string, unknown>;
|
|
49
|
+
createdAt: Date;
|
|
50
|
+
updatedAt: Date;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A single step in the evaluation trace, recording what was evaluated and the outcome.
|
|
55
|
+
*/
|
|
56
|
+
export interface EvaluationTrace {
|
|
57
|
+
type?: 'group' | 'condition';
|
|
58
|
+
operator?: 'AND' | 'OR' | 'NOT';
|
|
59
|
+
field?: string;
|
|
60
|
+
op?: string;
|
|
61
|
+
value?: unknown;
|
|
62
|
+
expected?: unknown;
|
|
63
|
+
actual?: unknown;
|
|
64
|
+
result?: boolean;
|
|
65
|
+
matched?: boolean;
|
|
66
|
+
children?: EvaluationTrace[];
|
|
67
|
+
durationMs?: number;
|
|
68
|
+
}
|
package/src/operators.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Full operator definition including the evaluate function.
|
|
11
|
+
* Used internally by the engine to evaluate conditions.
|
|
12
|
+
*/
|
|
13
|
+
export interface OperatorDefinition {
|
|
14
|
+
name?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
category?: string;
|
|
18
|
+
fieldTypes?: string[];
|
|
19
|
+
schema?: unknown;
|
|
20
|
+
evaluate: (fieldValue: unknown, conditionValue: unknown) => boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Discovery subset of an operator — excludes the evaluate function.
|
|
25
|
+
* Used for listing available operators to consumers.
|
|
26
|
+
*/
|
|
27
|
+
export interface OperatorInfo {
|
|
28
|
+
name: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
label?: string;
|
|
31
|
+
category?: string;
|
|
32
|
+
fieldTypes?: string[];
|
|
33
|
+
}
|