@gp2f/server 0.1.7 → 0.1.8
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/README.md +28 -0
- package/lib/policy-builder.js +12 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,6 +72,34 @@ async function main() {
|
|
|
72
72
|
main().catch(console.error);
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
### 3. Fluent Policy Builder
|
|
76
|
+
|
|
77
|
+
Build policy ASTs with a chainable API instead of raw JSON objects:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { p } from '@gp2f/server';
|
|
81
|
+
|
|
82
|
+
// Field equality
|
|
83
|
+
const policy = p.field('/role').eq('admin');
|
|
84
|
+
|
|
85
|
+
// Logical AND
|
|
86
|
+
const policy = p.and(
|
|
87
|
+
p.field('/role').eq('clinician'),
|
|
88
|
+
p.exists('/patient_id'),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Role allow-list
|
|
92
|
+
const policy = p.field('/role').in(['admin', 'editor', 'reviewer']);
|
|
93
|
+
|
|
94
|
+
// Numeric comparison
|
|
95
|
+
const policy = p.field('/score').gte(80);
|
|
96
|
+
|
|
97
|
+
// Vibe Engine gate
|
|
98
|
+
const policy = p.vibe('frustrated').withConfidence(0.8).build();
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The builder output is a plain `AstNode` that works with `evaluate()`, `evaluateWithTrace()`, `addActivity()`, and anywhere else a policy AST is accepted.
|
|
102
|
+
|
|
75
103
|
## Development
|
|
76
104
|
This package uses `napi-rs` to build the Rust bindings.
|
|
77
105
|
|
package/lib/policy-builder.js
CHANGED
|
@@ -32,47 +32,41 @@ class FieldBuilder {
|
|
|
32
32
|
_op(kind, value) {
|
|
33
33
|
return {
|
|
34
34
|
kind,
|
|
35
|
-
children: [
|
|
36
|
-
|
|
37
|
-
{ kind: 'Literal', value },
|
|
38
|
-
],
|
|
35
|
+
children: [{ kind: 'Field', path: this._path }],
|
|
36
|
+
value: String(value)
|
|
39
37
|
}
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
// Equality
|
|
43
|
-
equal(value) { return this._op('Eq',
|
|
41
|
+
equal(value) { return this._op('Eq', value) }
|
|
44
42
|
eq(value) { return this.equal(value) }
|
|
45
|
-
notEqual(value) { return this._op('Neq',
|
|
43
|
+
notEqual(value) { return this._op('Neq', value) }
|
|
46
44
|
neq(value) { return this.notEqual(value) }
|
|
47
45
|
|
|
48
46
|
// Comparisons
|
|
49
|
-
greaterThan(value) { return this._op('Gt',
|
|
47
|
+
greaterThan(value) { return this._op('Gt', value) }
|
|
50
48
|
gt(value) { return this.greaterThan(value) }
|
|
51
|
-
greaterThanOrEqual(value) { return this._op('Gte',
|
|
49
|
+
greaterThanOrEqual(value) { return this._op('Gte', value) }
|
|
52
50
|
gte(value) { return this.greaterThanOrEqual(value) }
|
|
53
|
-
lessThan(value) { return this._op('Lt',
|
|
51
|
+
lessThan(value) { return this._op('Lt', value) }
|
|
54
52
|
lt(value) { return this.lessThan(value) }
|
|
55
|
-
lessThanOrEqual(value) { return this._op('Lte',
|
|
53
|
+
lessThanOrEqual(value) { return this._op('Lte', value) }
|
|
56
54
|
lte(value) { return this.lessThanOrEqual(value) }
|
|
57
55
|
|
|
58
56
|
// Collection
|
|
59
57
|
in(values) {
|
|
60
58
|
return {
|
|
61
59
|
kind: 'In',
|
|
62
|
-
children: [
|
|
63
|
-
|
|
64
|
-
{ kind: 'Literal', value: JSON.stringify(values) },
|
|
65
|
-
],
|
|
60
|
+
children: [{ kind: 'Field', path: this._path }],
|
|
61
|
+
value: JSON.stringify(values)
|
|
66
62
|
}
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
contains(value) {
|
|
70
66
|
return {
|
|
71
67
|
kind: 'Contains',
|
|
72
|
-
children: [
|
|
73
|
-
|
|
74
|
-
{ kind: 'Literal', value },
|
|
75
|
-
],
|
|
68
|
+
children: [{ kind: 'Field', path: this._path }],
|
|
69
|
+
value: String(value)
|
|
76
70
|
}
|
|
77
71
|
}
|
|
78
72
|
|