@kensio/quando 0.2.0 → 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.
Files changed (63) hide show
  1. package/README.md +18 -8
  2. package/dist/assigned.d.ts +68 -0
  3. package/dist/assigned.d.ts.map +1 -0
  4. package/dist/assigned.js +84 -0
  5. package/dist/assigned.js.map +1 -0
  6. package/dist/canonical-rule.d.ts +23 -0
  7. package/dist/canonical-rule.d.ts.map +1 -0
  8. package/dist/canonical-rule.js +139 -0
  9. package/dist/canonical-rule.js.map +1 -0
  10. package/dist/canonical.d.ts +44 -0
  11. package/dist/canonical.d.ts.map +1 -0
  12. package/dist/canonical.js +53 -0
  13. package/dist/canonical.js.map +1 -0
  14. package/dist/cascade.d.ts +21 -0
  15. package/dist/cascade.d.ts.map +1 -1
  16. package/dist/cascade.js +13 -0
  17. package/dist/cascade.js.map +1 -1
  18. package/dist/index.d.ts +12 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +8 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/merge.d.ts +43 -0
  23. package/dist/merge.d.ts.map +1 -0
  24. package/dist/merge.js +79 -0
  25. package/dist/merge.js.map +1 -0
  26. package/dist/parse-cascade.d.ts +37 -0
  27. package/dist/parse-cascade.d.ts.map +1 -0
  28. package/dist/parse-cascade.js +105 -0
  29. package/dist/parse-cascade.js.map +1 -0
  30. package/dist/parse-fields.d.ts +7 -10
  31. package/dist/parse-fields.d.ts.map +1 -1
  32. package/dist/parse-fields.js +8 -36
  33. package/dist/parse-fields.js.map +1 -1
  34. package/dist/parse-shape.d.ts +39 -0
  35. package/dist/parse-shape.d.ts.map +1 -0
  36. package/dist/parse-shape.js +77 -0
  37. package/dist/parse-shape.js.map +1 -0
  38. package/dist/parse.d.ts.map +1 -1
  39. package/dist/parse.js +4 -26
  40. package/dist/parse.js.map +1 -1
  41. package/dist/query.d.ts +23 -17
  42. package/dist/query.d.ts.map +1 -1
  43. package/dist/query.js +25 -19
  44. package/dist/query.js.map +1 -1
  45. package/dist/resolve.d.ts +14 -8
  46. package/dist/resolve.d.ts.map +1 -1
  47. package/dist/resolve.js +41 -26
  48. package/dist/resolve.js.map +1 -1
  49. package/dist/rota.d.ts.map +1 -1
  50. package/dist/rota.js +2 -8
  51. package/dist/rota.js.map +1 -1
  52. package/dist/schedule.d.ts.map +1 -1
  53. package/dist/schedule.js +2 -7
  54. package/dist/schedule.js.map +1 -1
  55. package/dist/tally.d.ts +76 -0
  56. package/dist/tally.d.ts.map +1 -0
  57. package/dist/tally.js +80 -0
  58. package/dist/tally.js.map +1 -0
  59. package/dist/valued-stream.d.ts +19 -10
  60. package/dist/valued-stream.d.ts.map +1 -1
  61. package/dist/valued-stream.js +95 -24
  62. package/dist/valued-stream.js.map +1 -1
  63. package/package.json +22 -20
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EACL,WAAW,EACX,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,mBAAmB,EACnB,eAAe,GAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAgBnC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EACL,GAAG,EACH,MAAM,EACN,GAAG,EACH,KAAK,EACL,UAAU,EACV,MAAM,EACN,KAAK,EACL,GAAG,EACH,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AASvC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI5E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAKvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EACL,WAAW,EACX,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,mBAAmB,EACnB,eAAe,GAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAgBnC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EACL,GAAG,EACH,MAAM,EACN,GAAG,EACH,KAAK,EACL,UAAU,EACV,MAAM,EACN,KAAK,EACL,GAAG,EACH,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAS7D,OAAO,EACL,OAAO,EACP,SAAS,EACT,KAAK,EACL,MAAM,EACN,OAAO,EACP,QAAQ,GACT,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAKhE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * What overlap means when two layers claim the same moment.
3
+ *
4
+ * Precedence answers it one way. The later layer wins and the earlier one is
5
+ * displaced, which is what a rota and a schedule want: one person is on call,
6
+ * and a shop is open or it is shut. Some domains want the other answer. Two
7
+ * teams each putting three people on a Monday have six people on that Monday,
8
+ * and a tariff built from a standing charge and a peak rate is the sum of
9
+ * them.
10
+ *
11
+ * The strategy is a name in the document rather than a function passed to
12
+ * `resolve`. A function cannot be stored, so a cascade carrying one would be a
13
+ * document that no longer says what it means, and two readers of the same
14
+ * stored cascade could disagree about the answer. The cost is a closed
15
+ * vocabulary, which is the same trade the rule language already makes.
16
+ */
17
+ /**
18
+ * How overlapping layers combine.
19
+ *
20
+ * - `override` displaces. The later layer wins outright, and this is what a
21
+ * cascade does when it says nothing.
22
+ * - `sum`, `max` and `min` are arithmetic over numbers.
23
+ * - `concat` joins arrays, which is how a moment claimed by three layers comes
24
+ * back carrying all three.
25
+ */
26
+ export type MergeStrategy = "override" | "sum" | "max" | "min" | "concat";
27
+ export declare const MERGE_STRATEGIES: readonly MergeStrategy[];
28
+ /**
29
+ * Combines the value already accumulated with the one a later layer assigns.
30
+ *
31
+ * `under` is everything below, already folded. `over` is the layer being
32
+ * added. The order matters for `override` and for nothing else, which is why
33
+ * it is stated rather than left to the reader.
34
+ */
35
+ export type Merge<V> = (under: V, over: V) => V;
36
+ /**
37
+ * The function a named strategy stands for.
38
+ *
39
+ * An absent strategy is `override`, so a cascade written before merging
40
+ * existed means exactly what it did then.
41
+ */
42
+ export declare function mergeBy<V>(strategy: MergeStrategy | undefined): Merge<V>;
43
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE1E,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAMpD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;AAuChD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CA6BxE"}
package/dist/merge.js ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * What overlap means when two layers claim the same moment.
3
+ *
4
+ * Precedence answers it one way. The later layer wins and the earlier one is
5
+ * displaced, which is what a rota and a schedule want: one person is on call,
6
+ * and a shop is open or it is shut. Some domains want the other answer. Two
7
+ * teams each putting three people on a Monday have six people on that Monday,
8
+ * and a tariff built from a standing charge and a peak rate is the sum of
9
+ * them.
10
+ *
11
+ * The strategy is a name in the document rather than a function passed to
12
+ * `resolve`. A function cannot be stored, so a cascade carrying one would be a
13
+ * document that no longer says what it means, and two readers of the same
14
+ * stored cascade could disagree about the answer. The cost is a closed
15
+ * vocabulary, which is the same trade the rule language already makes.
16
+ */
17
+ export const MERGE_STRATEGIES = [
18
+ "override",
19
+ "sum",
20
+ "max",
21
+ "min",
22
+ "concat",
23
+ ];
24
+ /** What a value looks like, for an error message. */
25
+ function nameOf(value) {
26
+ if (value === null) {
27
+ return "null";
28
+ }
29
+ return Array.isArray(value) ? "an array" : typeof value;
30
+ }
31
+ /**
32
+ * The vocabulary is checked when a document is parsed. What the values in it
33
+ * turn out to be is only known once a cascade is resolved, so a `sum` over
34
+ * names fails here rather than at the boundary.
35
+ *
36
+ * The same split the rule language keeps. `parse.ts` checks shape and
37
+ * vocabulary, and meaning is settled where the thing is evaluated.
38
+ */
39
+ function wrongType(strategy, holds, found) {
40
+ throw new TypeError(`A cascade merging by "${strategy}" carries ${holds}, and this one holds ` +
41
+ `${nameOf(found)}. Give it values it can combine, or merge by "override".`);
42
+ }
43
+ function asNumber(strategy, value) {
44
+ return typeof value === "number"
45
+ ? value
46
+ : wrongType(strategy, "numbers", value);
47
+ }
48
+ function asArray(strategy, value) {
49
+ return Array.isArray(value) ? value : wrongType(strategy, "arrays", value);
50
+ }
51
+ /**
52
+ * The function a named strategy stands for.
53
+ *
54
+ * An absent strategy is `override`, so a cascade written before merging
55
+ * existed means exactly what it did then.
56
+ */
57
+ export function mergeBy(strategy) {
58
+ switch (strategy) {
59
+ case "sum": {
60
+ return (under, over) => (asNumber("sum", under) + asNumber("sum", over));
61
+ }
62
+ case "max": {
63
+ return (under, over) => Math.max(asNumber("max", under), asNumber("max", over));
64
+ }
65
+ case "min": {
66
+ return (under, over) => Math.min(asNumber("min", under), asNumber("min", over));
67
+ }
68
+ case "concat": {
69
+ return (under, over) => [...asArray("concat", under), ...asArray("concat", over)];
70
+ }
71
+ case "override":
72
+ case undefined: {
73
+ // The later layer displaces what is under it, which is the precedence a
74
+ // cascade has always had and what one says by saying nothing.
75
+ return (_under, over) => over;
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAaH,MAAM,CAAC,MAAM,gBAAgB,GAA6B;IACxD,UAAU;IACV,KAAK;IACL,KAAK;IACL,KAAK;IACL,QAAQ;CACT,CAAC;AAWF,qDAAqD;AACrD,SAAS,MAAM,CAAC,KAAc;IAC5B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC;AAC1D,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,SAAS,CAChB,QAAuB,EACvB,KAAa,EACb,KAAc;IAEd,MAAM,IAAI,SAAS,CACjB,yBAAyB,QAAQ,aAAa,KAAK,uBAAuB;QACxE,GAAG,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAC7E,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,QAAuB,EAAE,KAAc;IACvD,OAAO,OAAO,KAAK,KAAK,QAAQ;QAC9B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,OAAO,CAAC,QAAuB,EAAE,KAAc;IACtD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAI,QAAmC;IAC5D,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACrB,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAM,CAAC;QAC1D,CAAC;QAED,KAAK,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACrB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAM,CAAC;QACjE,CAAC;QAED,KAAK,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACrB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAM,CAAC;QACjE,CAAC;QAED,KAAK,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACrB,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAM,CAAC;QACnE,CAAC;QAED,KAAK,UAAU,CAAC;QAChB,KAAK,SAAS,EAAE,CAAC;YACf,wEAAwE;YACxE,8DAA8D;YAC9D,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Turning arbitrary JSON back into a cascade.
3
+ *
4
+ * The boundary `parseRule` keeps, one level up. A cascade is stored, sent and
5
+ * edited the way a rule is, so what comes back is whatever a database row, an
6
+ * API body or a form actually held, and the useful thing to do with a bad one
7
+ * is say precisely what is wrong and where.
8
+ *
9
+ * One thing differs, and it is why this takes an argument `parseRule` does
10
+ * not. The rule vocabulary is closed, so `parseRule` knows every rule there
11
+ * is. The values in a cascade are the caller's own domain type: a name, a
12
+ * tariff, a headcount. Quando has never seen one and has nothing to check it
13
+ * against, so the caller supplies the function that reads one.
14
+ */
15
+ import type { Cascade } from "./cascade.js";
16
+ /**
17
+ * Reads one stored value back at the type the caller keeps it in, or throws
18
+ * saying what is wrong.
19
+ *
20
+ * The `path` says where in the document the value sits, and belongs at the
21
+ * front of whatever the function throws. {@link fail} writes one in the same
22
+ * form the rest of parsing uses.
23
+ */
24
+ export type ValueParser<V> = (value: unknown, path: string) => V;
25
+ /**
26
+ * A cascade from unknown JSON, or a `TypeError` saying what is wrong and where.
27
+ *
28
+ * ```ts
29
+ * const onCall = parseCascade(JSON.parse(stored), asString);
30
+ * ```
31
+ *
32
+ * The `path` is what appears in front of every message, so a value six layers
33
+ * down reports as `cascade.layers[2].replace.layers[0].value` rather than as a
34
+ * puzzle.
35
+ */
36
+ export declare function parseCascade<V>(value: unknown, parseValue: ValueParser<V>, path?: string): Cascade<V>;
37
+ //# sourceMappingURL=parse-cascade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-cascade.d.ts","sourceRoot":"","sources":["../src/parse-cascade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAS,MAAM,cAAc,CAAC;AAKnD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC,CAAC;AAKjE;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,EAC1B,IAAI,SAAY,GACf,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Turning arbitrary JSON back into a cascade.
3
+ *
4
+ * The boundary `parseRule` keeps, one level up. A cascade is stored, sent and
5
+ * edited the way a rule is, so what comes back is whatever a database row, an
6
+ * API body or a form actually held, and the useful thing to do with a bad one
7
+ * is say precisely what is wrong and where.
8
+ *
9
+ * One thing differs, and it is why this takes an argument `parseRule` does
10
+ * not. The rule vocabulary is closed, so `parseRule` knows every rule there
11
+ * is. The values in a cascade are the caller's own domain type: a name, a
12
+ * tariff, a headcount. Quando has never seen one and has nothing to check it
13
+ * against, so the caller supplies the function that reads one.
14
+ */
15
+ import { MERGE_STRATEGIES } from "./merge.js";
16
+ import { asRecord, checkFields, fail, shapeOf } from "./parse-shape.js";
17
+ import { parseRule } from "./parse.js";
18
+ const CASCADE_FIELDS = ["merge", "layers"];
19
+ const LAYER_FIELDS = ["scope", "value", "replace"];
20
+ /**
21
+ * A cascade from unknown JSON, or a `TypeError` saying what is wrong and where.
22
+ *
23
+ * ```ts
24
+ * const onCall = parseCascade(JSON.parse(stored), asString);
25
+ * ```
26
+ *
27
+ * The `path` is what appears in front of every message, so a value six layers
28
+ * down reports as `cascade.layers[2].replace.layers[0].value` rather than as a
29
+ * puzzle.
30
+ */
31
+ export function parseCascade(value, parseValue, path = "cascade") {
32
+ const node = asRecord(value, path, "a cascade object");
33
+ const type = node["type"];
34
+ if (type !== "cascade") {
35
+ return fail(`${path}.type`, typeof type === "string"
36
+ ? `expected "cascade", found "${type}"`
37
+ : `expected "cascade", found ${shapeOf(type)}`);
38
+ }
39
+ checkFields(node, CASCADE_FIELDS, path, "a cascade");
40
+ const layers = node["layers"];
41
+ if (!Array.isArray(layers)) {
42
+ return fail(`${path}.layers`, `expected an array of layers, found ${shapeOf(layers)}`);
43
+ }
44
+ return {
45
+ type: "cascade",
46
+ ...mergePart(node, path),
47
+ layers: layers.map((layer, index) => parseLayer(layer, parseValue, `${path}.layers[${index}]`)),
48
+ };
49
+ }
50
+ /**
51
+ * Present or absent, never present-and-undefined, so a cascade that says
52
+ * nothing about merging serialises back to the document it came from.
53
+ *
54
+ * The name is checked here. Whether the values it will be handed are ones it
55
+ * can combine is not, because that is only known once the cascade is resolved.
56
+ */
57
+ function mergePart(node, path) {
58
+ const merge = node["merge"];
59
+ if (merge === undefined) {
60
+ return {};
61
+ }
62
+ if (!MERGE_STRATEGIES.includes(merge)) {
63
+ return fail(`${path}.merge`, typeof merge === "string"
64
+ ? `"${merge}" is not a merge strategy. Expected one of ${MERGE_STRATEGIES.join(", ")}`
65
+ : `expected a merge strategy, found ${shapeOf(merge)}`);
66
+ }
67
+ return { merge: merge };
68
+ }
69
+ /**
70
+ * One layer: where it applies, and what applies there.
71
+ *
72
+ * Order of complaint follows order of reading. What the layer covers is
73
+ * checked before what holds inside it, because a layer whose scope is broken
74
+ * has nothing worth saying about its value.
75
+ */
76
+ function parseLayer(value, parseValue, path) {
77
+ const node = asRecord(value, path, "a layer object");
78
+ // `checkFields` waves `type` past, because every rule and every cascade
79
+ // carries one. A layer does not, and a document that puts one here has
80
+ // confused the layer with the cascade holding it.
81
+ if ("type" in node) {
82
+ fail(`${path}.type`, "is not a field of a layer. The cascade around it carries the type");
83
+ }
84
+ checkFields(node, LAYER_FIELDS, path, "a layer");
85
+ const scope = parseRule(node["scope"], `${path}.scope`);
86
+ const holds = LAYER_FIELDS.filter((field) => field !== "scope" && field in node);
87
+ if (holds.length === 2) {
88
+ return fail(path, "has both a value and a replace, and a layer holds one or the other. " +
89
+ "A value applies across the whole scope, and a replace hands the " +
90
+ "scope to another cascade");
91
+ }
92
+ if (holds[0] === "replace") {
93
+ return {
94
+ scope,
95
+ replace: parseCascade(node["replace"], parseValue, `${path}.replace`),
96
+ };
97
+ }
98
+ if (holds[0] === "value") {
99
+ return { scope, value: parseValue(node["value"], `${path}.value`) };
100
+ }
101
+ return fail(path, "has neither a value nor a replace, so nothing holds inside its scope. " +
102
+ "A layer built with `undefined` as its value arrives this way, because " +
103
+ "`JSON.stringify` drops the field rather than writing it");
104
+ }
105
+ //# sourceMappingURL=parse-cascade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-cascade.js","sourceRoot":"","sources":["../src/parse-cascade.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,15 @@
1
1
  /**
2
2
  * Checking one field of an incoming rule document.
3
3
  *
4
- * Each of these either returns the value at the type it claims to be, or
5
- * throws saying what was found instead and where. The `path` threaded through
6
- * them is what turns "not a date" into
7
- * `rule.rules[1].rules[0].dates[0]: "not a date" is not a date`.
4
+ * These are the checks that know about time: a day of the week is one of
5
+ * seven names, a date is a date, a zone is one the runtime has heard of. Each
6
+ * either returns the value at the type it claims to be, or throws saying what
7
+ * was found instead and where.
8
+ *
9
+ * [parse-shape.ts](./parse-shape.ts) holds the ones underneath, which check
10
+ * that JSON is the shape it claims to be and know nothing about time.
8
11
  */
9
12
  import { type Weekday } from "./rule.js";
10
- export declare function fail(path: string, problem: string): never;
11
- /** What a value looks like, for an error message. */
12
- export declare function shapeOf(value: unknown): string;
13
- export declare function asRecord(value: unknown, path: string): Record<string, unknown>;
14
- export declare function asString(value: unknown, path: string): string;
15
- export declare function asStrings(value: unknown, path: string): string[];
16
13
  export declare function asDays(value: unknown, path: string): Weekday[];
17
14
  /** Checked by construction, so a malformed time is caught where it is written. */
18
15
  export declare function asTime(value: unknown, path: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"parse-fields.d.ts","sourceRoot":"","sources":["../src/parse-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAInD,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAEzD;AAED,qDAAqD;AACrD,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQ9C;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAShE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAS9D;AAED,kFAAkF;AAClF,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW3D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAY9D;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW3D;AAED,sDAAsD;AACtD,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAGnB"}
1
+ {"version":3,"file":"parse-fields.d.ts","sourceRoot":"","sources":["../src/parse-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAInD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAS9D;AAED,kFAAkF;AAClF,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW3D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAY9D;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW3D;AAED,sDAAsD;AACtD,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAGnB"}
@@ -1,45 +1,17 @@
1
1
  /**
2
2
  * Checking one field of an incoming rule document.
3
3
  *
4
- * Each of these either returns the value at the type it claims to be, or
5
- * throws saying what was found instead and where. The `path` threaded through
6
- * them is what turns "not a date" into
7
- * `rule.rules[1].rules[0].dates[0]: "not a date" is not a date`.
4
+ * These are the checks that know about time: a day of the week is one of
5
+ * seven names, a date is a date, a zone is one the runtime has heard of. Each
6
+ * either returns the value at the type it claims to be, or throws saying what
7
+ * was found instead and where.
8
+ *
9
+ * [parse-shape.ts](./parse-shape.ts) holds the ones underneath, which check
10
+ * that JSON is the shape it claims to be and know nothing about time.
8
11
  */
12
+ import { asString, asStrings, fail } from "./parse-shape.js";
9
13
  import { WEEKDAYS } from "./rule.js";
10
14
  const WEEKDAY_NAMES = new Set(WEEKDAYS);
11
- export function fail(path, problem) {
12
- throw new TypeError(`${path}: ${problem}`);
13
- }
14
- /** What a value looks like, for an error message. */
15
- export function shapeOf(value) {
16
- if (value === null) {
17
- return "null";
18
- }
19
- if (Array.isArray(value)) {
20
- return "an array";
21
- }
22
- return typeof value;
23
- }
24
- export function asRecord(value, path) {
25
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
26
- return fail(path, `expected a rule object, found ${shapeOf(value)}`);
27
- }
28
- return value;
29
- }
30
- export function asString(value, path) {
31
- return typeof value === "string"
32
- ? value
33
- : fail(path, `expected a string, found ${shapeOf(value)}`);
34
- }
35
- export function asStrings(value, path) {
36
- if (!Array.isArray(value)) {
37
- return fail(path, `expected an array, found ${shapeOf(value)}`);
38
- }
39
- return value.map((item, index) => typeof item === "string"
40
- ? item
41
- : fail(`${path}[${index}]`, `expected a string, found ${shapeOf(item)}`));
42
- }
43
15
  export function asDays(value, path) {
44
16
  return asStrings(value, path).map((day, index) => WEEKDAY_NAMES.has(day)
45
17
  ? day
@@ -1 +1 @@
1
- {"version":3,"file":"parse-fields.js","sourceRoot":"","sources":["../src/parse-fields.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse-fields.js","sourceRoot":"","sources":["../src/parse-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAgB,MAAM,WAAW,CAAC;AAEnD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,CAAC;AAEhD,MAAM,UAAU,MAAM,CAAC,KAAc,EAAE,IAAY;IACjD,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAC/C,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;QACpB,CAAC,CAAE,GAAe;QAClB,CAAC,CAAC,IAAI,CACF,GAAG,IAAI,IAAI,KAAK,GAAG,EACnB,IAAI,GAAG,+CAA+C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5E,CACN,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,MAAM,CAAC,KAAc,EAAE,IAAY;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CACT,IAAI,EACJ,IAAI,IAAI,yDAAyD,CAClE,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAc,EAAE,IAAY;IAClD,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAChD,IAAI,CAAC;YACH,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CACT,GAAG,IAAI,IAAI,KAAK,GAAG,EACnB,IAAI,IAAI,uDAAuD,CAChE,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,KAAc,EAAE,IAAY;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,eAAe,CAAC;YACpD,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,OAAO;SACnB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,4BAA4B,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,QAAQ,CACtB,IAA6B,EAC7B,IAAY;IAEZ,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,OAAO,CAAC,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Checking that incoming JSON is the shape it claims to be.
3
+ *
4
+ * Nothing here knows anything about time. These are the checks any document
5
+ * needs on the way in, and they say what was found instead and where. The
6
+ * `path` threaded through them is what turns "not a string" into
7
+ * `rule.rules[1].rules[0].dates[0]: expected a string, found number`.
8
+ *
9
+ * [parse-fields.ts](./parse-fields.ts) sits on top with the checks that do
10
+ * know about time, such as days of the week and zones.
11
+ */
12
+ export declare function fail(path: string, problem: string): never;
13
+ /** What a value looks like, for an error message. */
14
+ export declare function shapeOf(value: unknown): string;
15
+ /**
16
+ * `expected` names what should have been there, and reads straight into the
17
+ * message. "a rule object", "a layer object".
18
+ */
19
+ export declare function asRecord(value: unknown, path: string, expected: string): Record<string, unknown>;
20
+ /**
21
+ * Refuses a field the thing being parsed does not have.
22
+ *
23
+ * Quietly ignoring one is the worse option by some distance. A rule document
24
+ * carrying `"zonee"` would parse as a perfectly valid rule with no zone, which
25
+ * is a *different schedule* read in whatever zone the query happened to use,
26
+ * and nothing would have said so.
27
+ *
28
+ * The cost is that a document written by a later version of Quando, carrying a
29
+ * field this one has not heard of, is rejected rather than tolerated. That is
30
+ * the right way round. A field exists to change what a document means, so
31
+ * ignoring an unknown one is agreeing to get the answer wrong quietly.
32
+ *
33
+ * `type` is exempt, because every caller has already read it to get here.
34
+ */
35
+ export declare function checkFields(node: Record<string, unknown>, allowed: readonly string[], path: string, what: string): void;
36
+ export declare function asString(value: unknown, path: string): string;
37
+ export declare function asBoolean(value: unknown, path: string): boolean;
38
+ export declare function asStrings(value: unknown, path: string): string[];
39
+ //# sourceMappingURL=parse-shape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-shape.d.ts","sourceRoot":"","sources":["../src/parse-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAEzD;AAED,qDAAqD;AACrD,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQ9C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,IAAI,CAWN;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAI/D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAShE"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Checking that incoming JSON is the shape it claims to be.
3
+ *
4
+ * Nothing here knows anything about time. These are the checks any document
5
+ * needs on the way in, and they say what was found instead and where. The
6
+ * `path` threaded through them is what turns "not a string" into
7
+ * `rule.rules[1].rules[0].dates[0]: expected a string, found number`.
8
+ *
9
+ * [parse-fields.ts](./parse-fields.ts) sits on top with the checks that do
10
+ * know about time, such as days of the week and zones.
11
+ */
12
+ export function fail(path, problem) {
13
+ throw new TypeError(`${path}: ${problem}`);
14
+ }
15
+ /** What a value looks like, for an error message. */
16
+ export function shapeOf(value) {
17
+ if (value === null) {
18
+ return "null";
19
+ }
20
+ if (Array.isArray(value)) {
21
+ return "an array";
22
+ }
23
+ return typeof value;
24
+ }
25
+ /**
26
+ * `expected` names what should have been there, and reads straight into the
27
+ * message. "a rule object", "a layer object".
28
+ */
29
+ export function asRecord(value, path, expected) {
30
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
31
+ return fail(path, `expected ${expected}, found ${shapeOf(value)}`);
32
+ }
33
+ return value;
34
+ }
35
+ /**
36
+ * Refuses a field the thing being parsed does not have.
37
+ *
38
+ * Quietly ignoring one is the worse option by some distance. A rule document
39
+ * carrying `"zonee"` would parse as a perfectly valid rule with no zone, which
40
+ * is a *different schedule* read in whatever zone the query happened to use,
41
+ * and nothing would have said so.
42
+ *
43
+ * The cost is that a document written by a later version of Quando, carrying a
44
+ * field this one has not heard of, is rejected rather than tolerated. That is
45
+ * the right way round. A field exists to change what a document means, so
46
+ * ignoring an unknown one is agreeing to get the answer wrong quietly.
47
+ *
48
+ * `type` is exempt, because every caller has already read it to get here.
49
+ */
50
+ export function checkFields(node, allowed, path, what) {
51
+ for (const field of Object.keys(node)) {
52
+ if (field !== "type" && !allowed.includes(field)) {
53
+ fail(`${path}.${field}`, allowed.length === 0
54
+ ? `is not a field of ${what}, which takes none`
55
+ : `is not a field of ${what}. Expected ${allowed.join(", ")}`);
56
+ }
57
+ }
58
+ }
59
+ export function asString(value, path) {
60
+ return typeof value === "string"
61
+ ? value
62
+ : fail(path, `expected a string, found ${shapeOf(value)}`);
63
+ }
64
+ export function asBoolean(value, path) {
65
+ return typeof value === "boolean"
66
+ ? value
67
+ : fail(path, `expected a boolean, found ${shapeOf(value)}`);
68
+ }
69
+ export function asStrings(value, path) {
70
+ if (!Array.isArray(value)) {
71
+ return fail(path, `expected an array, found ${shapeOf(value)}`);
72
+ }
73
+ return value.map((item, index) => typeof item === "string"
74
+ ? item
75
+ : fail(`${path}[${index}]`, `expected a string, found ${shapeOf(item)}`));
76
+ }
77
+ //# sourceMappingURL=parse-shape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-shape.js","sourceRoot":"","sources":["../src/parse-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,OAAe;IAChD,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,OAAO,KAAK,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAc,EACd,IAAY,EACZ,QAAgB;IAEhB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,IAAI,CAAC,IAAI,EAAE,YAAY,QAAQ,WAAW,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,KAAgC,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,WAAW,CACzB,IAA6B,EAC7B,OAA0B,EAC1B,IAAY,EACZ,IAAY;IAEZ,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,IAAI,CACF,GAAG,IAAI,IAAI,KAAK,EAAE,EAClB,OAAO,CAAC,MAAM,KAAK,CAAC;gBAClB,CAAC,CAAC,qBAAqB,IAAI,oBAAoB;gBAC/C,CAAC,CAAC,qBAAqB,IAAI,cAAc,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChE,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc,EAAE,IAAY;IACnD,OAAO,OAAO,KAAK,KAAK,QAAQ;QAC9B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,4BAA4B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,IAAY;IACpD,OAAO,OAAO,KAAK,KAAK,SAAS;QAC/B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,6BAA6B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,IAAY;IACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,IAAI,EAAE,4BAA4B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC/B,OAAO,IAAI,KAAK,QAAQ;QACtB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,4BAA4B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAC3E,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAwDtC;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAS,GAAG,IAAI,CA+D7D"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAwBtC;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAS,GAAG,IAAI,CA+D7D"}
package/dist/parse.js CHANGED
@@ -11,7 +11,8 @@
11
11
  * rule *means* is not — `interpret.ts` owns that, and duplicating it here would
12
12
  * only give the two somewhere to disagree.
13
13
  */
14
- import { asDates, asDays, asRecord, asTime, fail, shapeOf, zonePart, } from "./parse-fields.js";
14
+ import { asDates, asDays, asTime, zonePart } from "./parse-fields.js";
15
+ import { asRecord, checkFields, fail, shapeOf } from "./parse-shape.js";
15
16
  /**
16
17
  * Every rule type, and the fields it is allowed to carry. One table rather than
17
18
  * two, so the list of known types and the list of known fields cannot drift.
@@ -26,29 +27,6 @@ const FIELDS = new Map([
26
27
  ["any", ["rules"]],
27
28
  ["not", ["rule"]],
28
29
  ]);
29
- /**
30
- * Refuses a field the rule type does not have.
31
- *
32
- * Quietly ignoring one is the worse option by some distance. A document
33
- * carrying `"zonee"` would parse as a perfectly valid rule with no zone, which
34
- * is a *different schedule* — read in whatever zone the query happened to use —
35
- * and nothing would have said so. The same goes for a `zone` on a rule type
36
- * that has no business with one.
37
- *
38
- * The cost is that a document written by a later version of Quando, carrying a
39
- * field this one has not heard of, is rejected rather than tolerated. That is
40
- * the right way round: a field exists to change what a rule means, so ignoring
41
- * an unknown one is agreeing to get the answer wrong quietly.
42
- */
43
- function checkFields(node, type, allowed, path) {
44
- for (const field of Object.keys(node)) {
45
- if (field !== "type" && !allowed.includes(field)) {
46
- fail(`${path}.${field}`, allowed.length === 0
47
- ? `is not a field of a ${type} rule, which takes none`
48
- : `is not a field of a ${type} rule. Expected ${allowed.join(", ")}`);
49
- }
50
- }
51
- }
52
30
  function asRules(value, path) {
53
31
  if (!Array.isArray(value)) {
54
32
  return fail(path, `expected an array of rules, found ${shapeOf(value)}`);
@@ -62,7 +40,7 @@ function asRules(value, path) {
62
40
  * deep reports as `rule.rules[2].rules[0].days[3]` rather than as a puzzle.
63
41
  */
64
42
  export function parseRule(value, path = "rule") {
65
- const node = asRecord(value, path);
43
+ const node = asRecord(value, path, "a rule object");
66
44
  const type = node["type"];
67
45
  if (typeof type !== "string") {
68
46
  return fail(`${path}.type`, `expected a string, found ${shapeOf(type)}`);
@@ -71,7 +49,7 @@ export function parseRule(value, path = "rule") {
71
49
  if (allowed === undefined) {
72
50
  return fail(`${path}.type`, `"${type}" is not a rule type. Expected one of ${[...FIELDS.keys()].join(", ")}`);
73
51
  }
74
- checkFields(node, type, allowed, path);
52
+ checkFields(node, allowed, path, `a ${type} rule`);
75
53
  switch (type) {
76
54
  case "always": {
77
55
  return { type: "always" };
package/dist/parse.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}