@texaryn/core 0.8.0 → 0.10.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/CHANGELOG.md +123 -0
- package/dist/commands/handler.d.ts +13 -0
- package/dist/commands/handler.d.ts.map +1 -1
- package/dist/commands/handler.js +22 -4
- package/dist/commands/handler.js.map +1 -1
- package/dist/commands/types.d.ts +16 -1
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/initialization/index.d.ts +4 -0
- package/dist/initialization/index.d.ts.map +1 -0
- package/dist/initialization/index.js +3 -0
- package/dist/initialization/index.js.map +1 -0
- package/dist/initialization/kernel.d.ts +133 -0
- package/dist/initialization/kernel.d.ts.map +1 -0
- package/dist/initialization/kernel.js +223 -0
- package/dist/initialization/kernel.js.map +1 -0
- package/dist/initialization/view.d.ts +16 -0
- package/dist/initialization/view.d.ts.map +1 -0
- package/dist/initialization/view.js +41 -0
- package/dist/initialization/view.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +106 -4
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +58 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/schema/port.d.ts +59 -11
- package/dist/schema/port.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/runtime/types.d.ts
CHANGED
|
@@ -4,11 +4,49 @@ import type { UIHints } from '../hints/types.js';
|
|
|
4
4
|
import type { Command } from '../commands/types.js';
|
|
5
5
|
import type { SubmissionState } from '../ir/runtime-state.js';
|
|
6
6
|
import type { NodeId, MaybePromise, ValidationError, VisibleError } from '../types.js';
|
|
7
|
+
import type { DefaultConflict, DefaultRefusal } from '../initialization/index.js';
|
|
8
|
+
/** Which initialization policy consumes the schema's `default` annotations. */
|
|
9
|
+
export type InitializationPolicy = 'none' | 'schema-defaults';
|
|
10
|
+
/**
|
|
11
|
+
* What one run of ADR-003's initialization pass did, without the data, which
|
|
12
|
+
* the runtime publishes on `data` like any other.
|
|
13
|
+
*
|
|
14
|
+
* A discarded run reports only that it was discarded. Carrying the conflicts
|
|
15
|
+
* and refusals of the run that produced them would say a run found them and
|
|
16
|
+
* then say nothing was written, and the two readings are not the same claim.
|
|
17
|
+
*/
|
|
18
|
+
export type InitializationReport = {
|
|
19
|
+
readonly outcome: 'initialized';
|
|
20
|
+
/** Locations left absent because their applicable declarations disagreed. */
|
|
21
|
+
readonly conflicts: readonly DefaultConflict[];
|
|
22
|
+
/** Locations left absent because filling would have meant guessing or destroying. */
|
|
23
|
+
readonly refusals: readonly DefaultRefusal[];
|
|
24
|
+
readonly passes: number;
|
|
25
|
+
} | {
|
|
26
|
+
readonly outcome: 'budget-exhausted';
|
|
27
|
+
readonly passes: number;
|
|
28
|
+
};
|
|
7
29
|
export interface FormRuntimeOptions {
|
|
8
30
|
initialData?: unknown;
|
|
9
31
|
hints?: UIHints;
|
|
10
32
|
onSubmit?: (data: unknown) => MaybePromise<void>;
|
|
11
33
|
validationDebounceMs?: number;
|
|
34
|
+
/**
|
|
35
|
+
* ADR-003. `'none'`, the default, materialises nothing: given `{}` the
|
|
36
|
+
* runtime's data stays `{}`.
|
|
37
|
+
*
|
|
38
|
+
* `'schema-defaults'` fills every reachable location the schema declares a
|
|
39
|
+
* default for and the data leaves absent. A location is filled when it
|
|
40
|
+
* becomes reachable, so this runs at construction, on `Reset`, and after any
|
|
41
|
+
* edit that can change what is reachable: activating a `oneOf` branch by
|
|
42
|
+
* setting its discriminator fills that branch's own defaults. It never
|
|
43
|
+
* overwrites, so `false`, `0`, `''` and `null` are values and are left alone.
|
|
44
|
+
*
|
|
45
|
+
* What the run wrote is the baseline at construction and on `Reset`, and is
|
|
46
|
+
* not between them: a location seeded by an edit differs from
|
|
47
|
+
* `state.initialData`, which is what `modified` reports.
|
|
48
|
+
*/
|
|
49
|
+
initialization?: InitializationPolicy;
|
|
12
50
|
}
|
|
13
51
|
export interface NodeState {
|
|
14
52
|
readonly value: Store<unknown>;
|
|
@@ -25,6 +63,26 @@ export interface FormRuntime {
|
|
|
25
63
|
readonly data: Store<unknown>;
|
|
26
64
|
readonly submission: Store<SubmissionState>;
|
|
27
65
|
readonly visibleErrors: Store<VisibleError[]>;
|
|
66
|
+
/**
|
|
67
|
+
* The last initialization run, or `undefined` where no policy is configured.
|
|
68
|
+
*
|
|
69
|
+
* `dispatch` returns void and is typically called from an event handler, so a
|
|
70
|
+
* run that exhausts its budget reports here rather than throwing into the
|
|
71
|
+
* host's render. What that discards depends on the moment: a `Reset`
|
|
72
|
+
* establishes a baseline, so it is refused whole and nothing lands, while an
|
|
73
|
+
* ordinary edit establishes none, so the edit lands and only the seeding is
|
|
74
|
+
* dropped. `createFormRuntime` throws instead, because a caller can decline a
|
|
75
|
+
* runtime it never received.
|
|
76
|
+
*
|
|
77
|
+
* A new report is published on every data-mutating dispatch under the policy,
|
|
78
|
+
* including one where the pass wrote nothing, because each dispatch is a run
|
|
79
|
+
* and what a run finds changes as the user types. Anything subscribed here
|
|
80
|
+
* therefore updates per edit.
|
|
81
|
+
*
|
|
82
|
+
* It is not the projection's diagnostics channel, which describes a schema
|
|
83
|
+
* rather than one run over data.
|
|
84
|
+
*/
|
|
85
|
+
readonly initialization: Store<InitializationReport | undefined>;
|
|
28
86
|
dispatch(command: Command): void;
|
|
29
87
|
getNodeState(nodeId: NodeId): NodeState | undefined;
|
|
30
88
|
destroy(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAEjF,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,iBAAiB,CAAA;AAE7D;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IACE,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAA;IAC9C,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAA;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErE,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,YAAY,CAAC,IAAI,CAAC,CAAA;IAChD,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,oBAAoB,CAAA;CACtC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAA;IACzC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAChC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IACjC,QAAQ,CAAC,gBAAgB,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC,CAAA;IAC1E,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACpC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAC7B,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;IAC3C,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAA;IAC7C;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,cAAc,EAAE,KAAK,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAA;IAChE,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAChC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;IACnD,OAAO,IAAI,IAAI,CAAA;CAChB"}
|
package/dist/schema/port.d.ts
CHANGED
|
@@ -8,17 +8,20 @@ export interface SchemaEvaluationPort {
|
|
|
8
8
|
export interface SchemaProjection {
|
|
9
9
|
nodes: Map<JsonPointer, NodeProjection>;
|
|
10
10
|
/**
|
|
11
|
-
* Every place the adapter could not choose
|
|
11
|
+
* Every place the adapter could not choose, and why.
|
|
12
12
|
*
|
|
13
|
-
* A pointer absent from `nodes` renders no field, and
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* make
|
|
13
|
+
* A pointer absent from `nodes` renders no field, and an annotation absent
|
|
14
|
+
* from a node states less than the schema does. Without this the caller
|
|
15
|
+
* cannot tell an intentional omission from a schema the adapter did not
|
|
16
|
+
* understand. That distinction is not cosmetic: a schema declaring a field
|
|
17
|
+
* the form silently never collects is the failure mode this exists to make
|
|
18
|
+
* visible.
|
|
18
19
|
*
|
|
19
|
-
* The rule the codes divide up: an explicit `type` is used, an
|
|
20
|
-
* structural shape is derived, and a schema that yields neither
|
|
21
|
-
* here.
|
|
20
|
+
* The rule the shape codes divide up: an explicit `type` is used, an
|
|
21
|
+
* unambiguous structural shape is derived, and a schema that yields neither
|
|
22
|
+
* is reported here. `ambiguous-default` is the same rule one level down, for
|
|
23
|
+
* a value rather than a shape. Nothing is guessed and nothing the schema
|
|
24
|
+
* declares disappears without a word.
|
|
22
25
|
*
|
|
23
26
|
* The boundary worth stating, because it is what keeps this channel worth
|
|
24
27
|
* reading: these describe schemas, not data.
|
|
@@ -38,11 +41,17 @@ export interface SchemaProjection {
|
|
|
38
41
|
*
|
|
39
42
|
* Optional, so an adapter that reports nothing stays valid, and empty rather
|
|
40
43
|
* than absent means "nothing to report".
|
|
44
|
+
*
|
|
45
|
+
* "Nothing to report" is per code rather than per adapter, and the
|
|
46
|
+
* conformance suite is what says which codes an adapter detects. An empty
|
|
47
|
+
* array is therefore not a claim that no code applies, only that none of the
|
|
48
|
+
* ones this adapter detects did.
|
|
41
49
|
*/
|
|
42
50
|
diagnostics?: readonly ProjectionDiagnostic[];
|
|
43
51
|
}
|
|
44
52
|
/**
|
|
45
|
-
* One reason a pointer
|
|
53
|
+
* One reason a pointer projects less than the schema declares: no node at all,
|
|
54
|
+
* or a node missing something the schema states.
|
|
46
55
|
*
|
|
47
56
|
* `code` is a stable identifier a caller can branch on; `message` is for a
|
|
48
57
|
* person reading a log and is not a contract.
|
|
@@ -51,6 +60,21 @@ export interface ProjectionDiagnostic {
|
|
|
51
60
|
pointer: JsonPointer;
|
|
52
61
|
code: ProjectionDiagnosticCode;
|
|
53
62
|
message: string;
|
|
63
|
+
/**
|
|
64
|
+
* The schema positions the diagnostic is about, as JSON Pointers into the
|
|
65
|
+
* schema document, with the root as the empty string. A position reached
|
|
66
|
+
* through `$ref` is named by what it resolves to rather than by the reference
|
|
67
|
+
* that pointed at it.
|
|
68
|
+
*
|
|
69
|
+
* Present where naming the positions is the useful half of the report, which
|
|
70
|
+
* is `ambiguous-default`: that two declarations disagree is far less
|
|
71
|
+
* actionable than which two. Optional because the other codes describe one
|
|
72
|
+
* schema position, already named by `pointer`.
|
|
73
|
+
*
|
|
74
|
+
* Order is not a contract. Which order an adapter walks its own applicators
|
|
75
|
+
* in is its own business; the set is what is being reported.
|
|
76
|
+
*/
|
|
77
|
+
sources?: readonly string[];
|
|
54
78
|
}
|
|
55
79
|
export type ProjectionDiagnosticCode =
|
|
56
80
|
/**
|
|
@@ -65,7 +89,22 @@ export type ProjectionDiagnosticCode =
|
|
|
65
89
|
* JSON Schema permits heterogeneous members, so `enum` says what the values
|
|
66
90
|
* are and not what type they have.
|
|
67
91
|
*/
|
|
68
|
-
| 'unresolved-projection-shape'
|
|
92
|
+
| 'unresolved-projection-shape'
|
|
93
|
+
/**
|
|
94
|
+
* Two or more `default` declarations apply to the location whatever the
|
|
95
|
+
* instance is, and they do not agree. `AnnotationSet.default` is omitted:
|
|
96
|
+
* one value is reported where the schema states one, and where it states two
|
|
97
|
+
* that disagree there is nothing to report but the disagreement.
|
|
98
|
+
*
|
|
99
|
+
* Unconditional is what makes this a fact about the schema. A location's own
|
|
100
|
+
* declaration and those reached from it through `allOf` and `$ref` all apply
|
|
101
|
+
* together, so no instance resolves them. Declarations that arrive through
|
|
102
|
+
* `oneOf`, `anyOf`, `if`/`then`/`else` or `dependentSchemas` are partitioned
|
|
103
|
+
* by the branch that carries them: they compete with each other within one
|
|
104
|
+
* branch, and a branch competing with the base is a state of the data, which
|
|
105
|
+
* this channel deliberately does not carry.
|
|
106
|
+
*/
|
|
107
|
+
| 'ambiguous-default';
|
|
69
108
|
export interface NodeProjection {
|
|
70
109
|
/**
|
|
71
110
|
* The shape a renderer should present, which is not an assertion about the
|
|
@@ -139,6 +178,15 @@ export interface AnnotationSet {
|
|
|
139
178
|
writeOnly?: boolean;
|
|
140
179
|
deprecated?: boolean;
|
|
141
180
|
examples?: unknown[];
|
|
181
|
+
/**
|
|
182
|
+
* The value the schema declares for a location that has none.
|
|
183
|
+
*
|
|
184
|
+
* Absent where two or more declarations apply unconditionally and disagree,
|
|
185
|
+
* with an `ambiguous-default` diagnostic in its place. A single value is
|
|
186
|
+
* reported where the schema states one; where it states two that disagree,
|
|
187
|
+
* reporting either would be a merge order presented as an answer, and the
|
|
188
|
+
* two adapters' merges do not even keep the same one.
|
|
189
|
+
*/
|
|
142
190
|
default?: unknown;
|
|
143
191
|
}
|
|
144
192
|
//# sourceMappingURL=port.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/schema/port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElE,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAAA;IAExC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAA;IAEvD,UAAU,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAA;CACjF;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;IACvC
|
|
1
|
+
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/schema/port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElE,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAAA;IAExC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAA;IAEvD,UAAU,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAA;CACjF;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;IACvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,WAAW,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,EAAE,wBAAwB,CAAA;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC5B;AAED,MAAM,MAAM,wBAAwB;AAClC;;;;GAIG;AACD,4BAA4B;AAC9B;;;;;GAKG;GACD,6BAA6B;AAC/B;;;;;;;;;;;;;GAaG;GACD,mBAAmB,CAAA;AAEvB,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;OASG;IACH,IAAI,EAAE,cAAc,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,gBAAgB,CAAA;IAC7B,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAA;IAC5B,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IACzB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAA;IACf;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,aAAa,CAAA;IAC1B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,aAAa,CAAA;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,WAAW,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,gFAAgF;IAChF,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB"}
|