@orkestrel/program 0.0.12 → 0.0.13
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 +15 -12
- package/dist/src/core/index.cjs +59 -34
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +86 -61
- package/dist/src/core/index.d.ts +86 -61
- package/dist/src/core/index.js +59 -34
- package/dist/src/core/index.js.map +1 -1
- package/package.json +17 -18
package/README.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
# @orkestrel/program
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
> The program composition layer: a pure, JSON-serializable `ProgramDefinition`
|
|
4
|
+
> that composes one qualification with an optional rating, plus notices,
|
|
5
|
+
> authority, and batch aggregate policy, and a `Program` that executes that
|
|
6
|
+
> definition in one direction — qualify, select, rate, derive status, then decide.
|
|
7
|
+
|
|
8
|
+
Build a definition with the `buildProgramDefinition` function, compile it with
|
|
9
|
+
`createProgram`, and call `execute` with one subject for a `ProgramResult` or
|
|
10
|
+
with a subject array for an `AggregateResult`. Execution never mutates its
|
|
11
|
+
inputs; every result is a fresh object. Injected qualifier, rater, and reason
|
|
12
|
+
instances stay caller-owned, and a standalone program owns the engine it creates.
|
|
13
|
+
Built over [`@orkestrel/qualifier`](https://github.com/orkestrel/qualifier),
|
|
14
|
+
[`@orkestrel/rater`](https://github.com/orkestrel/rater), and the shared
|
|
15
|
+
[`@orkestrel/reason`](https://github.com/orkestrel/reason) engine.
|
|
16
|
+
Environment-agnostic — no I/O, no browser or server assumptions. Part of the
|
|
17
|
+
`@orkestrel` line.
|
|
15
18
|
|
|
16
19
|
## Install
|
|
17
20
|
|
package/dist/src/core/index.cjs
CHANGED
|
@@ -5,9 +5,15 @@ let _orkestrel_rater = require("@orkestrel/rater");
|
|
|
5
5
|
let _orkestrel_reason = require("@orkestrel/reason");
|
|
6
6
|
let _orkestrel_emitter = require("@orkestrel/emitter");
|
|
7
7
|
//#region src/core/constants.ts
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Names the default definition validation policy, `true`, for `createProgram` /
|
|
10
|
+
* `ProgramManager.add`.
|
|
11
|
+
*/
|
|
9
12
|
var DEFAULT_PROGRAM_VALIDATE = true;
|
|
10
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Lists every {@link Status} literal in tally order — the source the union and its
|
|
15
|
+
* guard derive from.
|
|
16
|
+
*/
|
|
11
17
|
var STATUSES = Object.freeze([
|
|
12
18
|
"ineligible",
|
|
13
19
|
"referral",
|
|
@@ -21,19 +27,26 @@ var ELIGIBILITY_DECISIONS = Object.freeze({
|
|
|
21
27
|
ineligible: "denied",
|
|
22
28
|
referral: "submitted"
|
|
23
29
|
});
|
|
24
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Names the reserved working-subject key a batch's aggregate projection is written
|
|
32
|
+
* under, `'aggregate'`.
|
|
33
|
+
*/
|
|
25
34
|
var AGGREGATE_KEY = "aggregate";
|
|
26
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Names the reserved working-subject key the authority's outcome projection is
|
|
37
|
+
* written under, `'outcome'`.
|
|
38
|
+
*/
|
|
27
39
|
var OUTCOME_KEY = "outcome";
|
|
28
40
|
//#endregion
|
|
29
41
|
//#region src/core/errors.ts
|
|
30
42
|
/**
|
|
31
|
-
* Reports a coded programmer error thrown by the program layer
|
|
43
|
+
* Reports a coded programmer error thrown by the program layer, carrying a
|
|
44
|
+
* machine-readable code and an optional context and cause.
|
|
32
45
|
*
|
|
33
46
|
* @remarks
|
|
34
47
|
* `DUPLICATE` — a program id collision on `ProgramManager.add`, or a duplicate
|
|
35
|
-
* authored rating-line or notice id. `MISSING` — an
|
|
36
|
-
*
|
|
48
|
+
* authored rating-line or notice id. `MISSING` — an authored notice or
|
|
49
|
+
* qualification ruling scope names no rating line.
|
|
37
50
|
* `DEFINITION` — a program, qualification, rating, authority, or aggregate
|
|
38
51
|
* policy failed validation. `MISMATCH` — an injected entity or a returned
|
|
39
52
|
* reason result has the wrong contract. `RESERVED` — a subject already
|
|
@@ -453,7 +466,7 @@ function assertProgramSubject(subject) {
|
|
|
453
466
|
* A scope names a rating-line id. A line survives when its scope is absent
|
|
454
467
|
* (eligible by default), `eligible`, or a `condition` (which is not an
|
|
455
468
|
* eligibility value and never appears here). A scoped `ineligible` or `referral`
|
|
456
|
-
* removes the line
|
|
469
|
+
* removes the line before the rater is invoked — the excluded line is never
|
|
457
470
|
* evaluated merely to discard its amount.
|
|
458
471
|
*
|
|
459
472
|
* @param lines - The program's authored rating lines
|
|
@@ -481,9 +494,9 @@ function selectProgramLines(lines, scopes) {
|
|
|
481
494
|
* Explicit policy, not an opaque precedence reduce: global
|
|
482
495
|
* ineligibility or referral is terminal; a scoped referral yields `referral`;
|
|
483
496
|
* an applied `condition` or an applied scoped `restriction` (a line was
|
|
484
|
-
* removed but others rated) is `conditional`. When the definition
|
|
497
|
+
* removed but others rated) is `conditional`. When the definition omits
|
|
485
498
|
* `rating` the program is eligibility-only — status resolves to `conditional`
|
|
486
|
-
* or `eligible` and is
|
|
499
|
+
* or `eligible` and is never `unrated`. Otherwise a subject with no successful
|
|
487
500
|
* rating is `unrated`.
|
|
488
501
|
*
|
|
489
502
|
* @param definition - The authored program definition
|
|
@@ -634,8 +647,8 @@ function buildOutcomeProjection(result) {
|
|
|
634
647
|
* qualification succeeded, rating (when it ran) succeeded, and authority (when it
|
|
635
648
|
* ran) produced no errors — a valid ineligible or referral outcome still
|
|
636
649
|
* succeeds. `trace` and `errors` accumulate the qualification's, every rated
|
|
637
|
-
* line's worksheet trail, and the authority's. A `decision` is present
|
|
638
|
-
* an authority ran (`options.authority`), the execution
|
|
650
|
+
* line's worksheet trail, and the authority's. A `decision` is present only when
|
|
651
|
+
* an authority ran (`options.authority`), the execution succeeded (`success`),
|
|
639
652
|
* no `limit` determination applied, and status is not `unrated`.
|
|
640
653
|
*
|
|
641
654
|
* @param definition - The authored program definition
|
|
@@ -865,7 +878,7 @@ function validateProgramDefinition(definition, qualifier, engine) {
|
|
|
865
878
|
* @remarks
|
|
866
879
|
* The key is the resolved field coerced with `String` — `undefined` collapses
|
|
867
880
|
* to the empty string, so a subject missing the field and a subject whose
|
|
868
|
-
* field is literally `''` land in the
|
|
881
|
+
* field is literally `''` land in the same partition, and a numeric `1`
|
|
869
882
|
* collides with the string `'1'`.
|
|
870
883
|
*
|
|
871
884
|
* @param subject - The subject to key
|
|
@@ -886,7 +899,7 @@ function formatGroupKey(subject, partition) {
|
|
|
886
899
|
* Folds one subject's finite aggregate field values into a sums record.
|
|
887
900
|
*
|
|
888
901
|
* @remarks
|
|
889
|
-
* Returns a
|
|
902
|
+
* Returns a fresh record — `sums` is never mutated. Only finite numbers
|
|
890
903
|
* contribute; a non-numeric or absent value contributes zero (never a
|
|
891
904
|
* coercion). A {@link FieldPath} may be nested — `formatField` renders the
|
|
892
905
|
* dot-joined key the returned record is keyed by.
|
|
@@ -976,7 +989,7 @@ function aggregateGroups(subjects, fields, partition) {
|
|
|
976
989
|
*
|
|
977
990
|
* @remarks
|
|
978
991
|
* The projection carries the whole-batch `count` and `sums` plus the subject's
|
|
979
|
-
*
|
|
992
|
+
* own partition, located by the same {@link formatGroupKey} key
|
|
980
993
|
* {@link aggregateGroups} partitions under.
|
|
981
994
|
*
|
|
982
995
|
* @param subject - The subject to project for
|
|
@@ -1140,7 +1153,7 @@ function tallySubject(tallies, result, subject, fields) {
|
|
|
1140
1153
|
* @remarks
|
|
1141
1154
|
* `count` is the subject count, `trace` / `errors` accumulate every subject's
|
|
1142
1155
|
* plus the batch aggregate-gate evaluation's (`options.gates`), and `success`
|
|
1143
|
-
* requires every subject execution to succeed
|
|
1156
|
+
* requires every subject execution to succeed and the gate evaluation to have
|
|
1144
1157
|
* produced no errors. A fired aggregate gate contributes a `limit`
|
|
1145
1158
|
* determination, never a technical failure (a non-logical gate result is a
|
|
1146
1159
|
* caller-facing `MISMATCH` thrown by `Program` before this assembles).
|
|
@@ -1219,6 +1232,9 @@ function buildProgramDefinition(id, name, qualification, rating, input) {
|
|
|
1219
1232
|
/**
|
|
1220
1233
|
* Builds a fresh {@link Notice}.
|
|
1221
1234
|
*
|
|
1235
|
+
* @remarks
|
|
1236
|
+
* An absent `scope` is omitted entirely rather than stored as `undefined`.
|
|
1237
|
+
*
|
|
1222
1238
|
* @param id - The notice id
|
|
1223
1239
|
* @param message - The message template, carrying optional `{{token}}` placeholders
|
|
1224
1240
|
* @param input - Optional presentation scope
|
|
@@ -1241,6 +1257,10 @@ function buildNotice(id, message, input) {
|
|
|
1241
1257
|
/**
|
|
1242
1258
|
* Builds a fresh {@link AggregateDefinition}.
|
|
1243
1259
|
*
|
|
1260
|
+
* @remarks
|
|
1261
|
+
* `fields` is copied into a fresh array; an absent `partition` or `gates` is
|
|
1262
|
+
* omitted entirely rather than stored as `undefined`.
|
|
1263
|
+
*
|
|
1244
1264
|
* @param fields - The aggregate fields to sum across a batch
|
|
1245
1265
|
* @param input - Optional partition field and aggregate gates
|
|
1246
1266
|
* @returns A fresh aggregate definition
|
|
@@ -1262,15 +1282,15 @@ function buildAggregateDefinition(fields, input) {
|
|
|
1262
1282
|
//#endregion
|
|
1263
1283
|
//#region src/core/programs/Program.ts
|
|
1264
1284
|
/**
|
|
1265
|
-
* Composes one qualifier and one rater over a shared reason engine
|
|
1266
|
-
* single subjects or aggregate-aware batches.
|
|
1285
|
+
* Composes one qualifier and one rater over a shared reason engine, compiling one
|
|
1286
|
+
* authored definition and executing single subjects or aggregate-aware batches.
|
|
1267
1287
|
*
|
|
1268
1288
|
* @remarks
|
|
1269
1289
|
* Qualification decides whether rating happens: a globally ineligible, referred,
|
|
1270
1290
|
* or failed subject never reaches the rater, and a scoped ineligibility removes
|
|
1271
1291
|
* only its line before the first rating call. The rater always receives the
|
|
1272
|
-
*
|
|
1273
|
-
* qualifier, rater, or engine is injected the program creates
|
|
1292
|
+
* original subject; the qualifier's aggregate projection stays private. When no
|
|
1293
|
+
* qualifier, rater, or engine is injected the program creates one shared
|
|
1274
1294
|
* quantitative-plus-logical engine, injects it into the qualifier and rater it
|
|
1275
1295
|
* creates, and destroys only what it owns. A definition failure during
|
|
1276
1296
|
* construction (an invalid definition under `options.validate`) tears down
|
|
@@ -1280,8 +1300,8 @@ function buildAggregateDefinition(fields, input) {
|
|
|
1280
1300
|
* or `Date` reached through a reason `Check.value` is cloned but remains mutable
|
|
1281
1301
|
* because its contents live in internal slots. Uncloneable values and non-empty
|
|
1282
1302
|
* typed arrays are refused with `ProgramError('DEFINITION')` and the host error
|
|
1283
|
-
* as its cause. `destroy()` is idempotent and
|
|
1284
|
-
* flag is set
|
|
1303
|
+
* as its cause. `destroy()` is idempotent and reentrancy-safe — the destroyed
|
|
1304
|
+
* flag is set before any teardown or the `destroy` event fires, so a listener
|
|
1285
1305
|
* that re-enters `destroy()` is a no-op — and tears the emitter down last.
|
|
1286
1306
|
*/
|
|
1287
1307
|
var Program = class {
|
|
@@ -1409,7 +1429,7 @@ var Program = class {
|
|
|
1409
1429
|
* Destroys this program, idempotently.
|
|
1410
1430
|
*
|
|
1411
1431
|
* @remarks
|
|
1412
|
-
* The destroyed flag is set
|
|
1432
|
+
* The destroyed flag is set before any teardown or the `destroy` event, so a
|
|
1413
1433
|
* listener re-entering `destroy` is a no-op. An owned qualifier, rater, and reason
|
|
1414
1434
|
* engine are destroyed; an injected one stays caller-owned. The emitter is torn
|
|
1415
1435
|
* down last, and stays reachable afterwards.
|
|
@@ -1518,14 +1538,14 @@ var Program = class {
|
|
|
1518
1538
|
* qualifier, rater, and reason engine across every program it compiles.
|
|
1519
1539
|
*
|
|
1520
1540
|
* @remarks
|
|
1521
|
-
*
|
|
1541
|
+
* owns its ordered `#programs` collection and its own {@link Emitter} over
|
|
1522
1542
|
* {@link ProgramManagerEventMap}. Creates or borrows one shared engine, qualifier,
|
|
1523
1543
|
* and rater and injects the same instances into every compiled program. `remove`
|
|
1524
1544
|
* destroys the programs it removes; `destroy()` removes all programs, then
|
|
1525
|
-
* destroys only the owned shared dependencies, and tears the emitter down
|
|
1545
|
+
* destroys only the owned shared dependencies, and tears the emitter down last.
|
|
1526
1546
|
* A seed-program failure during construction tears the manager down (destroying
|
|
1527
1547
|
* whatever had already been compiled) before rethrowing the original error.
|
|
1528
|
-
* `destroy()` is
|
|
1548
|
+
* `destroy()` is reentrancy-safe — the destroyed flag is set before any teardown
|
|
1529
1549
|
* or the `remove` / `destroy` events fire, so a `remove` listener that re-enters
|
|
1530
1550
|
* `destroy()` is a no-op. Every call after `destroy()` throws {@link ProgramError}
|
|
1531
1551
|
* `'DESTROYED'`.
|
|
@@ -1735,7 +1755,7 @@ var ProgramManager = class {
|
|
|
1735
1755
|
* Destroys this manager, idempotently.
|
|
1736
1756
|
*
|
|
1737
1757
|
* @remarks
|
|
1738
|
-
* The destroyed flag is set
|
|
1758
|
+
* The destroyed flag is set before any teardown or the `remove` and `destroy`
|
|
1739
1759
|
* events, so a `remove` listener re-entering `destroy` is a no-op. Compiled
|
|
1740
1760
|
* programs are destroyed first, then an owned qualifier, rater, and reason engine;
|
|
1741
1761
|
* an injected one stays caller-owned. The emitter is torn down last, and stays
|
|
@@ -1782,34 +1802,39 @@ var ProgramManager = class {
|
|
|
1782
1802
|
//#endregion
|
|
1783
1803
|
//#region src/core/factories.ts
|
|
1784
1804
|
/**
|
|
1785
|
-
* Creates one compiled
|
|
1805
|
+
* Creates one compiled {@link ProgramInterface} over a qualifier and rater.
|
|
1786
1806
|
*
|
|
1787
1807
|
* @remarks
|
|
1788
1808
|
* If `options.validate` is `true`, the program validates the definition at
|
|
1789
1809
|
* construction; if `false`, it compiles the definition unvalidated. Default:
|
|
1790
|
-
* {@link DEFAULT_PROGRAM_VALIDATE}. A standalone program creates and
|
|
1791
|
-
*
|
|
1792
|
-
*
|
|
1810
|
+
* {@link DEFAULT_PROGRAM_VALIDATE}. A standalone program creates and owns one
|
|
1811
|
+
* shared quantitative-plus-logical reason engine and injects it into the qualifier
|
|
1812
|
+
* and rater it creates; injected dependencies remain caller-owned.
|
|
1793
1813
|
*
|
|
1794
1814
|
* @param definition - The authored program definition
|
|
1795
1815
|
* @param options - Optional injected qualifier, rater, engine, validation, labels, and emitter hooks
|
|
1796
1816
|
* @returns A {@link ProgramInterface}
|
|
1797
1817
|
*
|
|
1798
|
-
* @example
|
|
1818
|
+
* @example Compile a program and a manager
|
|
1799
1819
|
* ```ts
|
|
1800
|
-
* import { buildProgramDefinition, createProgram } from '@orkestrel/program'
|
|
1820
|
+
* import { buildProgramDefinition, createProgram, createProgramManager } from '@orkestrel/program'
|
|
1801
1821
|
*
|
|
1802
1822
|
* const definition = buildProgramDefinition('standard', 'Standard', qualification, rating)
|
|
1823
|
+
*
|
|
1803
1824
|
* const program = createProgram(definition)
|
|
1825
|
+
* const manager = createProgramManager({ programs: [definition] })
|
|
1826
|
+
*
|
|
1804
1827
|
* program.execute({ id: 'risk-1' })
|
|
1828
|
+
*
|
|
1805
1829
|
* program.destroy()
|
|
1830
|
+
* manager.destroy()
|
|
1806
1831
|
* ```
|
|
1807
1832
|
*/
|
|
1808
1833
|
function createProgram(definition, options) {
|
|
1809
1834
|
return new Program(definition, options);
|
|
1810
1835
|
}
|
|
1811
1836
|
/**
|
|
1812
|
-
* Creates one ordered
|
|
1837
|
+
* Creates one ordered {@link ProgramManagerInterface} over compiled programs.
|
|
1813
1838
|
*
|
|
1814
1839
|
* @remarks
|
|
1815
1840
|
* Creates or borrows one shared reason engine, qualifier, and rater and injects
|