@maroonedog/luq 2.2.0 → 2.3.1

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 (144) hide show
  1. package/README.md +47 -602
  2. package/dist/builder/compile-declarations.d.ts +7 -1
  3. package/dist/builder/compile-declarations.js +18 -8
  4. package/dist/builder/compile-declarations.mjs +18 -8
  5. package/dist/builder/create-builder.js +2 -3
  6. package/dist/builder/create-builder.mjs +2 -3
  7. package/dist/builder/create-field-builder.js +13 -1
  8. package/dist/builder/create-field-builder.mjs +13 -1
  9. package/dist/builder/declared-calls-store.d.ts +9 -0
  10. package/dist/builder/declared-calls-store.js +19 -0
  11. package/dist/builder/declared-calls-store.mjs +15 -0
  12. package/dist/builder/field-declared-calls.types.d.ts +6 -0
  13. package/dist/builder/field-declared-calls.types.js +2 -0
  14. package/dist/builder/field-declared-calls.types.mjs +1 -0
  15. package/dist/builder/field-entry.types.d.ts +9 -3
  16. package/dist/builder/field-options.types.d.ts +26 -0
  17. package/dist/chain/bundle-paths.types.d.ts +9 -12
  18. package/dist/chain/chain-node-store.d.ts +5 -0
  19. package/dist/chain/chain-node-store.js +15 -0
  20. package/dist/chain/chain-node-store.mjs +11 -0
  21. package/dist/chain/collect-field-rules.d.ts +13 -2
  22. package/dist/chain/collect-field-rules.js +10 -3
  23. package/dist/chain/collect-field-rules.mjs +10 -3
  24. package/dist/chain/create-chain-node.d.ts +10 -0
  25. package/dist/chain/create-chain-node.js +19 -9
  26. package/dist/chain/create-chain-node.mjs +19 -9
  27. package/dist/chain/create-field-slots.js +9 -1
  28. package/dist/chain/create-field-slots.mjs +9 -1
  29. package/dist/chain/declaration-recorder.port.d.ts +31 -0
  30. package/dist/chain/declaration-recorder.port.js +17 -0
  31. package/dist/chain/declaration-recorder.port.mjs +13 -0
  32. package/dist/chain/declared-call.types.d.ts +15 -0
  33. package/dist/chain/declared-call.types.js +2 -0
  34. package/dist/chain/declared-call.types.mjs +1 -0
  35. package/dist/chain/index.d.ts +3 -1
  36. package/dist/chain/slot-type-guard.d.ts +10 -0
  37. package/dist/chain/slot-type-guard.js +37 -0
  38. package/dist/chain/slot-type-guard.mjs +34 -0
  39. package/dist/compile/compile-array-node.js +1 -0
  40. package/dist/compile/compile-array-node.mjs +1 -0
  41. package/dist/compile/compile-field.d.ts +1 -0
  42. package/dist/compile/compile-field.js +8 -6
  43. package/dist/compile/compile-field.mjs +8 -6
  44. package/dist/compile/compile-schema.js +4 -0
  45. package/dist/compile/compile-schema.mjs +4 -0
  46. package/dist/compile/group-array-fields.d.ts +1 -0
  47. package/dist/compile/split-rules-by-kind.js +10 -14
  48. package/dist/compile/split-rules-by-kind.mjs +10 -14
  49. package/dist/compile/validation-plan.types.d.ts +19 -6
  50. package/dist/core/type-erasure.d.ts +36 -30
  51. package/dist/core/type-erasure.js +36 -30
  52. package/dist/core/type-erasure.mjs +36 -30
  53. package/dist/json-schema/build-from-schema.js +8 -1
  54. package/dist/json-schema/build-from-schema.mjs +8 -1
  55. package/dist/json-schema/create-structural-context.js +3 -0
  56. package/dist/json-schema/create-structural-context.mjs +3 -0
  57. package/dist/json-schema/declare-additional-properties.d.ts +7 -7
  58. package/dist/json-schema/declare-additional-properties.js +7 -7
  59. package/dist/json-schema/declare-additional-properties.mjs +7 -7
  60. package/dist/json-schema/declare-object-keywords.js +4 -4
  61. package/dist/json-schema/declare-object-keywords.mjs +4 -4
  62. package/dist/json-schema/follow-json-pointer.d.ts +7 -6
  63. package/dist/json-schema/follow-json-pointer.js +24 -24
  64. package/dist/json-schema/follow-json-pointer.mjs +24 -24
  65. package/dist/json-schema/ref-resolution-error.js +3 -3
  66. package/dist/json-schema/ref-resolution-error.mjs +3 -3
  67. package/dist/json-schema/schema-registry.js +12 -11
  68. package/dist/json-schema/schema-registry.mjs +12 -11
  69. package/dist/json-schema/uri-reference.js +12 -12
  70. package/dist/json-schema/uri-reference.mjs +12 -12
  71. package/dist/path/create-value-writer.js +12 -12
  72. package/dist/path/create-value-writer.mjs +12 -12
  73. package/dist/path/reserved-segment.d.ts +16 -16
  74. package/dist/path/reserved-segment.js +17 -21
  75. package/dist/path/reserved-segment.mjs +17 -21
  76. package/dist/plugins/index.generated.js +2 -2
  77. package/dist/plugins/index.generated.mjs +2 -2
  78. package/dist/plugins/manifest.generated.js +2 -2
  79. package/dist/plugins/manifest.generated.mjs +2 -2
  80. package/dist/plugins/object/object.d.ts +6 -0
  81. package/dist/plugins/object/object.js +9 -11
  82. package/dist/plugins/object/object.mjs +10 -12
  83. package/dist/plugins/object-additional-properties/select-additional-keys.d.ts +8 -8
  84. package/dist/plugins/object-additional-properties/select-additional-keys.js +16 -16
  85. package/dist/plugins/object-additional-properties/select-additional-keys.mjs +16 -16
  86. package/dist/plugins/stitch/stitch.d.ts +10 -14
  87. package/dist/plugins/stitch-with/stitch-with.d.ts +1 -1
  88. package/dist/plugins/stitch-with/stitch-with.js +22 -24
  89. package/dist/plugins/stitch-with/stitch-with.mjs +22 -24
  90. package/dist/plugins/string-min/string-min.js +6 -8
  91. package/dist/plugins/string-min/string-min.mjs +6 -8
  92. package/dist/presets/presets.d.ts +10 -11
  93. package/dist/presets/presets.js +22 -23
  94. package/dist/presets/presets.mjs +22 -23
  95. package/dist/runtime/create-field-validator.js +4 -6
  96. package/dist/runtime/create-field-validator.mjs +4 -6
  97. package/dist/runtime/create-validator.js +11 -11
  98. package/dist/runtime/create-validator.mjs +11 -11
  99. package/dist/runtime/output-writer.js +5 -1
  100. package/dist/runtime/output-writer.mjs +5 -1
  101. package/dist/runtime/run-array-node.js +6 -6
  102. package/dist/runtime/run-array-node.mjs +6 -6
  103. package/dist/runtime/run-field.js +18 -19
  104. package/dist/runtime/run-field.mjs +18 -19
  105. package/dist/standard-schema/assemble-json-schema.d.ts +4 -0
  106. package/dist/standard-schema/assemble-json-schema.js +95 -0
  107. package/dist/standard-schema/assemble-json-schema.mjs +92 -0
  108. package/dist/standard-schema/declaration-recorder.d.ts +6 -0
  109. package/dist/standard-schema/declaration-recorder.js +30 -0
  110. package/dist/standard-schema/declaration-recorder.mjs +27 -0
  111. package/dist/standard-schema/declarations-unavailable-error.d.ts +4 -0
  112. package/dist/standard-schema/declarations-unavailable-error.js +32 -0
  113. package/dist/standard-schema/declarations-unavailable-error.mjs +28 -0
  114. package/dist/standard-schema/emit-field-schema.d.ts +9 -0
  115. package/dist/standard-schema/emit-field-schema.js +68 -0
  116. package/dist/standard-schema/emit-field-schema.mjs +65 -0
  117. package/dist/standard-schema/index.d.ts +5 -0
  118. package/dist/standard-schema/index.js +9 -1
  119. package/dist/standard-schema/index.mjs +4 -0
  120. package/dist/standard-schema/json-schema-target.d.ts +6 -0
  121. package/dist/standard-schema/json-schema-target.js +44 -0
  122. package/dist/standard-schema/json-schema-target.mjs +39 -0
  123. package/dist/standard-schema/plugin-keyword-map.d.ts +3 -0
  124. package/dist/standard-schema/plugin-keyword-map.js +93 -0
  125. package/dist/standard-schema/plugin-keyword-map.mjs +90 -0
  126. package/dist/standard-schema/split-issue-path.d.ts +6 -4
  127. package/dist/standard-schema/split-issue-path.js +15 -13
  128. package/dist/standard-schema/split-issue-path.mjs +15 -13
  129. package/dist/standard-schema/standard-schema.types.d.ts +8 -7
  130. package/dist/standard-schema/standard-schema.types.js +6 -6
  131. package/dist/standard-schema/standard-schema.types.mjs +6 -6
  132. package/dist/standard-schema/to-standard-json-schema.d.ts +19 -0
  133. package/dist/standard-schema/to-standard-json-schema.js +36 -0
  134. package/dist/standard-schema/to-standard-json-schema.mjs +33 -0
  135. package/dist/standard-schema/to-standard-schema.d.ts +16 -15
  136. package/dist/standard-schema/to-standard-schema.js +15 -22
  137. package/dist/standard-schema/to-standard-schema.mjs +15 -22
  138. package/dist/standard-schema/unrepresentable-rule-error.d.ts +15 -0
  139. package/dist/standard-schema/unrepresentable-rule-error.js +43 -0
  140. package/dist/standard-schema/unrepresentable-rule-error.mjs +38 -0
  141. package/dist/types/index.d.ts +12 -12
  142. package/dist/types/index.js +7 -7
  143. package/dist/types/index.mjs +7 -7
  144. package/package.json +1 -1
@@ -1,22 +1,22 @@
1
1
  // ===========================================================================
2
2
  // L7 src/plugins/object-additional-properties/select-additional-keys.ts
3
3
  //
4
- // additional なキー」を選ぶ規則。boolean 形とスキーマ形の両方が使う。
4
+ // Which keys count as "additional". Used by both the boolean form and the
5
+ // schema form.
5
6
  //
6
- // Draft-07 §6.5.4 additionalProperties の対象を「properties にも
7
- // patternProperties にも該当しないキー」と定めている。パターンを見落とすと
8
- // `{"patternProperties":{"^v":{}},"additionalProperties":false}`
9
- // {"vroom":2} を誤って拒否する (スイートの
10
- // "patternProperties are not additional properties" がそれを突く)。
7
+ // Draft-07 §6.5.4 defines them as the keys matched by neither `properties`
8
+ // nor `patternProperties`. Miss the patterns and
9
+ // `{"patternProperties":{"^v":{}},"additionalProperties":false}` wrongly
10
+ // rejects {"vroom":2}.
11
11
  // ===========================================================================
12
12
  /**
13
- * パターンは build 時に一度だけコンパイルする。実行時は回すだけ、という
14
- * 設計に合わせるためで、キーごとに new RegExp すると O(キー数 x パターン数)
15
- * のコンパイルが毎回走る。
13
+ * Patterns are compiled once, at build time, matching the design where
14
+ * validation only runs what was already assembled. Compiling per key would
15
+ * cost O(keys × patterns) compilations on every call.
16
16
  *
17
- * 壊れた正規表現は無視する。スキーマ側の誤りでビルド全体を落とすより、
18
- * そのパターンが誰にも一致しないほうがまし (Draft-07 ECMA-262
19
- * 正規表現を求めるが、方言差で通らないものが現実には来る)。
17
+ * A broken pattern is ignored rather than fatal. Draft-07 asks for ECMA-262
18
+ * regular expressions and real documents arrive with dialect differences;
19
+ * having that one pattern match nothing beats refusing the whole build.
20
20
  */
21
21
  export function compilePatterns(patterns) {
22
22
  if (patterns === undefined || patterns.length === 0)
@@ -28,19 +28,19 @@ export function compilePatterns(patterns) {
28
28
  }
29
29
  catch {
30
30
  try {
31
- // "u" が付くと通らない書き方が現実にはある。付けずにもう一度試す。
31
+ // Some real patterns fail only under "u". Try again without it.
32
32
  compiled.push(new RegExp(pattern));
33
33
  }
34
34
  catch {
35
- // どちらでも駄目なら、このパターンは一致しないものとして扱う。
35
+ // Failing both ways, treat this pattern as matching nothing.
36
36
  }
37
37
  }
38
38
  }
39
39
  return Object.freeze(compiled);
40
40
  }
41
41
  /**
42
- * 宣言済みのキー名にも、どのパターンにも該当しないキーを返す。
43
- * 返る配列は入力の列挙順を保つ (issue のメッセージが安定する)。
42
+ * Returns the keys matched by neither a declared name nor any pattern,
43
+ * preserving the input's enumeration order so issue output stays stable.
44
44
  */
45
45
  export function selectAdditionalKeys(value, known, patterns) {
46
46
  return Object.keys(value).filter((key) => !known.has(key) && !patterns.some((pattern) => pattern.test(key)));
@@ -5,11 +5,10 @@ import type { FieldRefs, StitchOut } from "../../plugin-kit/marker.types";
5
5
  * The bundle handed to the check at RUN TIME, keyed by the path exactly as
6
6
  * declared.
7
7
  *
8
- * 呼び出し側がこれを見ることはもう無い。`.stitch(["price"], ...)` と書いた
9
- * 時点でパスの集合は分かっているので、述語が受け取る束の型は
10
- * `PickPaths<TRoot, F>` として組まれる (src/chain/chain-method.types.ts
11
- * StitchOut の腕)。この型が残っているのは、実行時に集める側が「キーは
12
- * パス文字列」という事実を書き留めておく場所だからである。
8
+ * Callers no longer see this type. Writing `.stitch(["price"], ...)` already
9
+ * fixes the set of paths, so the bundle the predicate receives is typed per
10
+ * key from those paths. What survives here is the run-time side's record of
11
+ * one fact: the keys are the path strings.
13
12
  */
14
13
  export type StitchFieldValues = Readonly<Record<string, unknown>>;
15
14
  /**
@@ -22,19 +21,16 @@ export type StitchFieldValues = Readonly<Record<string, unknown>>;
22
21
  */
23
22
  export type StitchFieldsOf<TRoot, TFields extends readonly string[]> = PickPaths<TRoot, TFields>;
24
23
  /**
25
- * 1.x `{ valid, message? }`、名前も形もそのまま。実体は src/types
26
- * CrossFieldOutcome で、チェーン層が呼び出し側の型を組むのに参照する
27
- * L3 から L7 import しないための置き場である。
24
+ * The legacy `{ valid, message? }`, name and shape unchanged. It is declared
25
+ * where the chain layer can reach it, so that layer never has to import a
26
+ * plugin to build a caller-facing type.
28
27
  */
29
28
  export type StitchOutcome = CrossFieldOutcome;
30
29
  /**
31
- * 実行時に build() が受け取る形。**呼び出し側が見る型ではない。**
30
+ * The shape build() receives at run time. **Not the type a caller sees.**
32
31
  *
33
- * `.stitch(["price", "quantity"], ...)` と書いた時点でパスの集合は分かって
34
- * いるので、述語が受け取る束は `PickPaths<TRoot, F>` として組まれ、キーごとに
35
- * 値の型が付く (src/chain/chain-method.types.ts の StitchOut の腕)。
36
- * ここが `Record<string, unknown>` のままだったのが、その腕を足すまでの
37
- * stitch である。
32
+ * Writing `.stitch(["price", "quantity"], ...)` already fixes the set of
33
+ * paths, so the bundle the predicate receives is typed per key.
38
34
  */
39
35
  export type StitchCheck = (fieldValues: StitchFieldValues, value: unknown, root: unknown) => StitchOutcome;
40
36
  /** 1.x's messageFactory context for this plugin, minus the re-run. */
@@ -1,6 +1,6 @@
1
1
  import type { MessageContextExtra } from "../../types";
2
2
  import type { BundleOut, NarrowedChain } from "../../plugin-kit/marker.types";
3
- /** 別名 -> ルートのパス。実行時はただの文字列の対応表である。 */
3
+ /** Alias to a path from the root. At run time, a table of strings. */
4
4
  export type BundleAliasMap = Readonly<Record<string, string>>;
5
5
  export interface StitchWithExtra extends MessageContextExtra {
6
6
  readonly aliases: readonly string[];
@@ -3,38 +3,36 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.stitchWithPlugin = void 0;
4
4
  // ===========================================================================
5
5
  // L7 src/plugins/stitch-with/stitch-with.ts — EXPERIMENTAL.
6
- // `stitch` の型付き後継。クロスフィールド検証のためのメソッドである。
6
+ // The typed successor to `stitch`, for cross-field validation.
7
7
  //
8
- // stitch の核は「**複数のフィールドを1つの判定にまとめる**」ことなので、
9
- // 主体は束そのものであって、別名ごとではない。別名ごとにルールを並べる形も
10
- // 書けるが、それでは `total === price * quantity` が書けず、stitch では
11
- // なくなる。
8
+ // The point of stitching is to bring SEVERAL FIELDS INTO ONE JUDGEMENT, so
9
+ // the subject is the bundle itself and not each alias. Listing rules per alias
10
+ // is writable but cannot express `total === price * quantity`, at which point
11
+ // it is no longer stitching.
12
12
  //
13
- // stitch との違いは一点だけである。stitch は束を
14
- // `Readonly<Record<string, unknown>>` として手書きの述語に渡すので、束の中身に
15
- // ついて型が何も言わない。ここでは束が対応表から組まれて **型が付く**:
13
+ // One difference from `stitch`. There the bundle reaches the predicate as
14
+ // `Readonly<Record<string, unknown>>`, so the type says nothing about its
15
+ // contents. Here the bundle is assembled from a mapping and IS TYPED:
16
16
  //
17
17
  // .v("total", (b) => b.number.stitchWith(
18
18
  // { cost: "price", count: "quantity" },
19
19
  // (f) => f.object.custom((bundle) => bundle.cost * bundle.count === 100)
20
20
  // ))
21
21
  //
22
- // `bundle` `{ cost: number; count: number }` であって Record ではない。
23
- // メンバー名を綴り違えれば、型を取り違えれば、コンパイルエラーになる。
22
+ // `bundle` is `{ cost: number; count: number }`, not a Record. Misspell a
23
+ // member or mistake its type and it fails to compile.
24
24
  //
25
- // なぜ別名を経由するのか。束をパス文字列でキーすると、その文字列は宣言の場で
26
- // **パスとして** 解釈される: `"user.name"` は束の中の `user.name` を探しに
27
- // 行き、束は平たいので見つからない (実測して分かった)。別名は素の識別子なので
28
- // その衝突が起きず、参照できるのは宣言した別名だけになる。
25
+ // Why aliases rather than paths as keys. A path string used as a bundle key is
26
+ // interpreted AS A PATH where it is declared, so `"user.name"` goes looking
27
+ // for `user.name` inside the bundle and never finds it, the bundle being
28
+ // flat. An alias is a bare identifier, so that collision cannot happen and the
29
+ // only things referable are the aliases actually declared.
29
30
  //
30
- // このファイルに判定は無い。サブチェーンは NarrowedChain と同じ経路で
31
- // `readonly Rule[]` に解決され、branch がそれを枝にし、エンジンが走らせる。
32
- // 束専用の収集器をコアに置く案も作って動かしたが、実測でコアが 220 B 増えた
33
- // (7,590 -> 7,810 B)。stitchWith を使わない利用者が払う形なので採らなかった。
34
- // 既存の経路に乗せると追加は 0 B である。
35
- //
36
- // 1.x が同じ責務の実装を3つ持っていたのは、ここで「もう1つ書く」を選んだ
37
- // からである。
31
+ // No judgement happens in this file. The sub-chain resolves to
32
+ // `readonly Rule[]` through the same route a narrowed chain takes, and the
33
+ // engine runs it. A bundle-specific collector in the core was built and
34
+ // measured; it added bytes to everyone who never stitches, so this rides the
35
+ // existing route instead and adds none.
38
36
  // ===========================================================================
39
37
  const types_1 = require("../../types");
40
38
  const create_rule_1 = require("../../plugin-kit/create-rule");
@@ -57,7 +55,7 @@ function readMembers(aliasMap) {
57
55
  read: (0, index_1.createValueReader)((0, index_1.parseFieldPath)(path)),
58
56
  })));
59
57
  }
60
- /** ルートから束を組む。枝の主体はこのオブジェクトになる。 */
58
+ /** Assembles the bundle from the root; this object is the branch's subject. */
61
59
  function collectBundle(members, root) {
62
60
  const bundle = {};
63
61
  for (const member of members)
@@ -76,7 +74,7 @@ exports.stitchWithPlugin = (0, plugin_definition_1.definePlugin)()({
76
74
  messageFactory: ctx.messageFactory,
77
75
  severity: ctx.severity,
78
76
  branches: [(0, create_rule_1.branch)(BUNDLE_BRANCH_LABEL, rules)],
79
- // 主体の値は見ない。見るのはルートから組んだ束だけである。
77
+ // The field's own value is not read. Only the assembled bundle is.
80
78
  combine: (runners) => {
81
79
  const runner = runners[0];
82
80
  if (runner === undefined)
@@ -1,37 +1,35 @@
1
1
  // ===========================================================================
2
2
  // L7 src/plugins/stitch-with/stitch-with.ts — EXPERIMENTAL.
3
- // `stitch` の型付き後継。クロスフィールド検証のためのメソッドである。
3
+ // The typed successor to `stitch`, for cross-field validation.
4
4
  //
5
- // stitch の核は「**複数のフィールドを1つの判定にまとめる**」ことなので、
6
- // 主体は束そのものであって、別名ごとではない。別名ごとにルールを並べる形も
7
- // 書けるが、それでは `total === price * quantity` が書けず、stitch では
8
- // なくなる。
5
+ // The point of stitching is to bring SEVERAL FIELDS INTO ONE JUDGEMENT, so
6
+ // the subject is the bundle itself and not each alias. Listing rules per alias
7
+ // is writable but cannot express `total === price * quantity`, at which point
8
+ // it is no longer stitching.
9
9
  //
10
- // stitch との違いは一点だけである。stitch は束を
11
- // `Readonly<Record<string, unknown>>` として手書きの述語に渡すので、束の中身に
12
- // ついて型が何も言わない。ここでは束が対応表から組まれて **型が付く**:
10
+ // One difference from `stitch`. There the bundle reaches the predicate as
11
+ // `Readonly<Record<string, unknown>>`, so the type says nothing about its
12
+ // contents. Here the bundle is assembled from a mapping and IS TYPED:
13
13
  //
14
14
  // .v("total", (b) => b.number.stitchWith(
15
15
  // { cost: "price", count: "quantity" },
16
16
  // (f) => f.object.custom((bundle) => bundle.cost * bundle.count === 100)
17
17
  // ))
18
18
  //
19
- // `bundle` `{ cost: number; count: number }` であって Record ではない。
20
- // メンバー名を綴り違えれば、型を取り違えれば、コンパイルエラーになる。
19
+ // `bundle` is `{ cost: number; count: number }`, not a Record. Misspell a
20
+ // member or mistake its type and it fails to compile.
21
21
  //
22
- // なぜ別名を経由するのか。束をパス文字列でキーすると、その文字列は宣言の場で
23
- // **パスとして** 解釈される: `"user.name"` は束の中の `user.name` を探しに
24
- // 行き、束は平たいので見つからない (実測して分かった)。別名は素の識別子なので
25
- // その衝突が起きず、参照できるのは宣言した別名だけになる。
22
+ // Why aliases rather than paths as keys. A path string used as a bundle key is
23
+ // interpreted AS A PATH where it is declared, so `"user.name"` goes looking
24
+ // for `user.name` inside the bundle and never finds it, the bundle being
25
+ // flat. An alias is a bare identifier, so that collision cannot happen and the
26
+ // only things referable are the aliases actually declared.
26
27
  //
27
- // このファイルに判定は無い。サブチェーンは NarrowedChain と同じ経路で
28
- // `readonly Rule[]` に解決され、branch がそれを枝にし、エンジンが走らせる。
29
- // 束専用の収集器をコアに置く案も作って動かしたが、実測でコアが 220 B 増えた
30
- // (7,590 -> 7,810 B)。stitchWith を使わない利用者が払う形なので採らなかった。
31
- // 既存の経路に乗せると追加は 0 B である。
32
- //
33
- // 1.x が同じ責務の実装を3つ持っていたのは、ここで「もう1つ書く」を選んだ
34
- // からである。
28
+ // No judgement happens in this file. The sub-chain resolves to
29
+ // `readonly Rule[]` through the same route a narrowed chain takes, and the
30
+ // engine runs it. A bundle-specific collector in the core was built and
31
+ // measured; it added bytes to everyone who never stitches, so this rides the
32
+ // existing route instead and adds none.
35
33
  // ===========================================================================
36
34
  import { PASS, fail, isPlainObject } from "../../types/index.mjs";
37
35
  import { branch, composite } from "../../plugin-kit/create-rule.mjs";
@@ -54,7 +52,7 @@ function readMembers(aliasMap) {
54
52
  read: createValueReader(parseFieldPath(path)),
55
53
  })));
56
54
  }
57
- /** ルートから束を組む。枝の主体はこのオブジェクトになる。 */
55
+ /** Assembles the bundle from the root; this object is the branch's subject. */
58
56
  function collectBundle(members, root) {
59
57
  const bundle = {};
60
58
  for (const member of members)
@@ -73,7 +71,7 @@ export const stitchWithPlugin = /*#__PURE__*/ definePlugin()({
73
71
  messageFactory: ctx.messageFactory,
74
72
  severity: ctx.severity,
75
73
  branches: [branch(BUNDLE_BRANCH_LABEL, rules)],
76
- // 主体の値は見ない。見るのはルートから組んだ束だけである。
74
+ // The field's own value is not read. Only the assembled bundle is.
77
75
  combine: (runners) => {
78
76
  const runner = runners[0];
79
77
  if (runner === undefined)
@@ -23,17 +23,15 @@ exports.stringMinPlugin = (0, plugin_definition_1.definePlugin)()({
23
23
  code: ctx.code,
24
24
  messageFactory: ctx.messageFactory,
25
25
  severity: ctx.severity,
26
- // min に届いた時点で止める。全長を数える必要があるのは**落ちる**
27
- // ときだけで、そのときは値が min より短いのだから走査も短い。
28
- // 元は countCodePoints を最大二度呼び、どちらも文字列を最後まで
29
- // 歩いていた。符号位置で数えるのは変えない (UTF-16 単位ではない)
30
- // 変えているのは、いつ止めるかだけである。受理パスで 12.7%。
26
+ // Stops as soon as min is reached. The full length is only needed to
27
+ // REPORT a failure, and a failing value is shorter than min, so that
28
+ // walk is short too. Counting is still by code point, not UTF-16 unit;
29
+ // the only thing that changed is when it stops.
31
30
  run: (value) => {
32
31
  if (!(0, types_1.isString)(value))
33
32
  return types_1.PASS;
34
- // min 0 なら空文字列も通る。ループは空文字列で一度も回らないので、
35
- // この行が無いと `""` actual 0 で落ちる 早期脱出に書き換えた
36
- // ときに実際に開いた穴で、既存のテストは一件も気づかなかった。
33
+ // min of 0 admits the empty string. The loop body never runs on an
34
+ // empty string, so without this line the empty string fails with 0.
37
35
  if (min === 0)
38
36
  return types_1.PASS;
39
37
  let count = 0;
@@ -20,17 +20,15 @@ export const stringMinPlugin = /*#__PURE__*/ definePlugin()({
20
20
  code: ctx.code,
21
21
  messageFactory: ctx.messageFactory,
22
22
  severity: ctx.severity,
23
- // min に届いた時点で止める。全長を数える必要があるのは**落ちる**
24
- // ときだけで、そのときは値が min より短いのだから走査も短い。
25
- // 元は countCodePoints を最大二度呼び、どちらも文字列を最後まで
26
- // 歩いていた。符号位置で数えるのは変えない (UTF-16 単位ではない)
27
- // 変えているのは、いつ止めるかだけである。受理パスで 12.7%。
23
+ // Stops as soon as min is reached. The full length is only needed to
24
+ // REPORT a failure, and a failing value is shorter than min, so that
25
+ // walk is short too. Counting is still by code point, not UTF-16 unit;
26
+ // the only thing that changed is when it stops.
28
27
  run: (value) => {
29
28
  if (!isString(value))
30
29
  return PASS;
31
- // min 0 なら空文字列も通る。ループは空文字列で一度も回らないので、
32
- // この行が無いと `""` actual 0 で落ちる 早期脱出に書き換えた
33
- // ときに実際に開いた穴で、既存のテストは一件も気づかなかった。
30
+ // min of 0 admits the empty string. The loop body never runs on an
31
+ // empty string, so without this line the empty string fails with 0.
34
32
  if (min === 0)
35
33
  return PASS;
36
34
  let count = 0;
@@ -1,6 +1,5 @@
1
1
  /**
2
- * 在る・無い・null。ほぼ全ての宣言がこの三つのどれかを使う。
3
- * 使用実績: required 138 / optional 26 / nullable 12。
2
+ * Present, absent, null. Nearly every declaration uses one of the three.
4
3
  */
5
4
  export declare const presence: Readonly<{
6
5
  required: import("..").PluginDefinition<"required", "required", readonly import("..").TypeName[], {
@@ -19,7 +18,7 @@ export declare const presence: Readonly<{
19
18
  context: import("..").MessageContextExtra;
20
19
  }>;
21
20
  }>;
22
- /** 文字列の定番。使用実績: stringMin 95 / stringEmail 33 / stringPattern 12。 */
21
+ /** The everyday string checks. */
23
22
  export declare const strings: Readonly<{
24
23
  stringMin: import("..").PluginDefinition<"stringMin", "min", readonly ["string"], {
25
24
  args: readonly [min: number];
@@ -46,7 +45,7 @@ export declare const strings: Readonly<{
46
45
  };
47
46
  }>;
48
47
  }>;
49
- /** 数値の定番。使用実績: numberMin 43 / numberMax 8。 */
48
+ /** The everyday number checks. */
50
49
  export declare const numbers: Readonly<{
51
50
  numberMin: import("..").PluginDefinition<"numberMin", "min", readonly ["number"], {
52
51
  args: readonly [min: number, exclusive?: boolean];
@@ -64,7 +63,7 @@ export declare const numbers: Readonly<{
64
63
  context: import("..").MessageContextExtra;
65
64
  }>;
66
65
  }>;
67
- /** 配列の定番。要素ごとの規則は arrayEach が運ぶ。 */
66
+ /** The everyday array checks. Per-element rules ride on arrayEach. */
68
67
  export declare const arrays: Readonly<{
69
68
  arrayMinLength: import("..").PluginDefinition<"arrayMinLength", "minLength", readonly ["array", "tuple"], {
70
69
  args: readonly [min: number];
@@ -83,14 +82,14 @@ export declare const arrays: Readonly<{
83
82
  }>;
84
83
  }>;
85
84
  /**
86
- * 上の四つを合わせたもの。13プラグイン、gzip +1,452 B。
85
+ * The four bundles above, together.
87
86
  *
88
- * 名前が「common」でないのは、それが何も言っていないからである
89
- * (lint の禁止語彙にも入っている)。入っているのは presence と、文字列・数値・
90
- * 配列それぞれの定番で、毎日書くのはこの範囲だ、という主張がこの名前である。
87
+ * Not called "common", because that name says nothing — and lint bans it. It
88
+ * holds presence plus the everyday string, number and array checks, and the
89
+ * name is the claim that this is the range people write day to day.
91
90
  *
92
- * これでも「全部入り」ではない。全部入りが要るなら `@maroonedog/luq/plugins`
93
- * のバレルがあり、そちらは 77 個ぶん、gzip で +17,986 B を払う。
91
+ * Still not everything. For everything there is the `@maroonedog/luq/plugins`
92
+ * barrel, which costs accordingly.
94
93
  */
95
94
  export declare const everydayRules: Readonly<{
96
95
  arrayMinLength: import("..").PluginDefinition<"arrayMinLength", "minLength", readonly ["array", "tuple"], {
@@ -2,24 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.everydayRules = exports.arrays = exports.numbers = exports.strings = exports.presence = void 0;
4
4
  // ===========================================================================
5
- // L7 src/presets/presets.ts — 事前定義したプラグイン束。
5
+ // L7 src/presets/presets.ts — predefined plugin bundles.
6
6
  //
7
- // なぜ要るのか。プラグインを1つずつ import するのは「使った分しか入らない」
8
- // を成り立たせている仕組みそのものだが、最初の一本を書くのに15行の use()
9
- // 並べさせるのは、その正しさの押し付けである。
7
+ // Why they exist. Importing plugins one at a time is the very mechanism behind
8
+ // "you only ship what you used", but making someone write fifteen use() lines
9
+ // for their first validator is imposing that correctness on them.
10
10
  //
11
- // なぜ「小さいのを複数」なのか。全部入りを1つ置くと、5個しか要らない人が
12
- // 40個分のバイトを払う。束は型としてはただの `PluginBag` なので、必要な束
13
- // だけを `useAll()` すればよく、混ぜても first-wins で衝突しない:
11
+ // Why several small ones rather than one big one. A single everything-bundle
12
+ // bills the person who needs five plugins for forty. A bundle is just a
13
+ // `PluginBag`, so useAll() takes only the ones wanted, and mixing them is
14
+ // first-wins rather than a collision:
14
15
  //
15
16
  // Builder().useAll(presence).useAll(strings).for<User>()
16
17
  //
17
- // 何を入れるかはリポジトリ内の使用実績から決めた (test/ docs-site/
18
- // use() を数えたもの)。required 138 / stringMin 95 / numberMin 43 /
19
- // stringEmail 33 / optional 26 という並びで、上位が束の中身になっている。
18
+ // Membership was chosen from how often each plugin is actually used across
19
+ // this repository, most-used first.
20
20
  //
21
- // バイト数は config/size-budget.json が測る。プリセットは便利さと引き換えに
22
- // バイトを払うものなので、いくら払うかは書いてあるべきである。
21
+ // What a bundle costs in bytes is measured by the size budget. A preset trades
22
+ // bytes for convenience, so the price should be measured rather than asserted.
23
23
  // ===========================================================================
24
24
  const required_1 = require("../plugins/required");
25
25
  const optional_1 = require("../plugins/optional");
@@ -35,42 +35,41 @@ const array_min_length_1 = require("../plugins/array-min-length");
35
35
  const array_max_length_1 = require("../plugins/array-max-length");
36
36
  const array_each_1 = require("../plugins/array-each");
37
37
  /**
38
- * 在る・無い・null。ほぼ全ての宣言がこの三つのどれかを使う。
39
- * 使用実績: required 138 / optional 26 / nullable 12。
38
+ * Present, absent, null. Nearly every declaration uses one of the three.
40
39
  */
41
40
  exports.presence = Object.freeze({
42
41
  required: required_1.requiredPlugin,
43
42
  optional: optional_1.optionalPlugin,
44
43
  nullable: nullable_1.nullablePlugin,
45
44
  });
46
- /** 文字列の定番。使用実績: stringMin 95 / stringEmail 33 / stringPattern 12。 */
45
+ /** The everyday string checks. */
47
46
  exports.strings = Object.freeze({
48
47
  stringMin: string_min_1.stringMinPlugin,
49
48
  stringMax: string_max_1.stringMaxPlugin,
50
49
  stringPattern: string_pattern_1.stringPatternPlugin,
51
50
  stringEmail: string_email_1.stringEmailPlugin,
52
51
  });
53
- /** 数値の定番。使用実績: numberMin 43 / numberMax 8。 */
52
+ /** The everyday number checks. */
54
53
  exports.numbers = Object.freeze({
55
54
  numberMin: number_min_1.numberMinPlugin,
56
55
  numberMax: number_max_1.numberMaxPlugin,
57
56
  numberInteger: number_integer_1.numberIntegerPlugin,
58
57
  });
59
- /** 配列の定番。要素ごとの規則は arrayEach が運ぶ。 */
58
+ /** The everyday array checks. Per-element rules ride on arrayEach. */
60
59
  exports.arrays = Object.freeze({
61
60
  arrayMinLength: array_min_length_1.arrayMinLengthPlugin,
62
61
  arrayMaxLength: array_max_length_1.arrayMaxLengthPlugin,
63
62
  arrayEach: array_each_1.arrayEachPlugin,
64
63
  });
65
64
  /**
66
- * 上の四つを合わせたもの。13プラグイン、gzip +1,452 B。
65
+ * The four bundles above, together.
67
66
  *
68
- * 名前が「common」でないのは、それが何も言っていないからである
69
- * (lint の禁止語彙にも入っている)。入っているのは presence と、文字列・数値・
70
- * 配列それぞれの定番で、毎日書くのはこの範囲だ、という主張がこの名前である。
67
+ * Not called "common", because that name says nothing — and lint bans it. It
68
+ * holds presence plus the everyday string, number and array checks, and the
69
+ * name is the claim that this is the range people write day to day.
71
70
  *
72
- * これでも「全部入り」ではない。全部入りが要るなら `@maroonedog/luq/plugins`
73
- * のバレルがあり、そちらは 77 個ぶん、gzip で +17,986 B を払う。
71
+ * Still not everything. For everything there is the `@maroonedog/luq/plugins`
72
+ * barrel, which costs accordingly.
74
73
  */
75
74
  exports.everydayRules = Object.freeze({
76
75
  ...exports.presence,
@@ -1,22 +1,22 @@
1
1
  // ===========================================================================
2
- // L7 src/presets/presets.ts — 事前定義したプラグイン束。
2
+ // L7 src/presets/presets.ts — predefined plugin bundles.
3
3
  //
4
- // なぜ要るのか。プラグインを1つずつ import するのは「使った分しか入らない」
5
- // を成り立たせている仕組みそのものだが、最初の一本を書くのに15行の use()
6
- // 並べさせるのは、その正しさの押し付けである。
4
+ // Why they exist. Importing plugins one at a time is the very mechanism behind
5
+ // "you only ship what you used", but making someone write fifteen use() lines
6
+ // for their first validator is imposing that correctness on them.
7
7
  //
8
- // なぜ「小さいのを複数」なのか。全部入りを1つ置くと、5個しか要らない人が
9
- // 40個分のバイトを払う。束は型としてはただの `PluginBag` なので、必要な束
10
- // だけを `useAll()` すればよく、混ぜても first-wins で衝突しない:
8
+ // Why several small ones rather than one big one. A single everything-bundle
9
+ // bills the person who needs five plugins for forty. A bundle is just a
10
+ // `PluginBag`, so useAll() takes only the ones wanted, and mixing them is
11
+ // first-wins rather than a collision:
11
12
  //
12
13
  // Builder().useAll(presence).useAll(strings).for<User>()
13
14
  //
14
- // 何を入れるかはリポジトリ内の使用実績から決めた (test/ docs-site/
15
- // use() を数えたもの)。required 138 / stringMin 95 / numberMin 43 /
16
- // stringEmail 33 / optional 26 という並びで、上位が束の中身になっている。
15
+ // Membership was chosen from how often each plugin is actually used across
16
+ // this repository, most-used first.
17
17
  //
18
- // バイト数は config/size-budget.json が測る。プリセットは便利さと引き換えに
19
- // バイトを払うものなので、いくら払うかは書いてあるべきである。
18
+ // What a bundle costs in bytes is measured by the size budget. A preset trades
19
+ // bytes for convenience, so the price should be measured rather than asserted.
20
20
  // ===========================================================================
21
21
  import { requiredPlugin } from "../plugins/required/index.mjs";
22
22
  import { optionalPlugin } from "../plugins/optional/index.mjs";
@@ -32,42 +32,41 @@ import { arrayMinLengthPlugin } from "../plugins/array-min-length/index.mjs";
32
32
  import { arrayMaxLengthPlugin } from "../plugins/array-max-length/index.mjs";
33
33
  import { arrayEachPlugin } from "../plugins/array-each/index.mjs";
34
34
  /**
35
- * 在る・無い・null。ほぼ全ての宣言がこの三つのどれかを使う。
36
- * 使用実績: required 138 / optional 26 / nullable 12。
35
+ * Present, absent, null. Nearly every declaration uses one of the three.
37
36
  */
38
37
  export const presence = Object.freeze({
39
38
  required: requiredPlugin,
40
39
  optional: optionalPlugin,
41
40
  nullable: nullablePlugin,
42
41
  });
43
- /** 文字列の定番。使用実績: stringMin 95 / stringEmail 33 / stringPattern 12。 */
42
+ /** The everyday string checks. */
44
43
  export const strings = Object.freeze({
45
44
  stringMin: stringMinPlugin,
46
45
  stringMax: stringMaxPlugin,
47
46
  stringPattern: stringPatternPlugin,
48
47
  stringEmail: stringEmailPlugin,
49
48
  });
50
- /** 数値の定番。使用実績: numberMin 43 / numberMax 8。 */
49
+ /** The everyday number checks. */
51
50
  export const numbers = Object.freeze({
52
51
  numberMin: numberMinPlugin,
53
52
  numberMax: numberMaxPlugin,
54
53
  numberInteger: numberIntegerPlugin,
55
54
  });
56
- /** 配列の定番。要素ごとの規則は arrayEach が運ぶ。 */
55
+ /** The everyday array checks. Per-element rules ride on arrayEach. */
57
56
  export const arrays = Object.freeze({
58
57
  arrayMinLength: arrayMinLengthPlugin,
59
58
  arrayMaxLength: arrayMaxLengthPlugin,
60
59
  arrayEach: arrayEachPlugin,
61
60
  });
62
61
  /**
63
- * 上の四つを合わせたもの。13プラグイン、gzip +1,452 B。
62
+ * The four bundles above, together.
64
63
  *
65
- * 名前が「common」でないのは、それが何も言っていないからである
66
- * (lint の禁止語彙にも入っている)。入っているのは presence と、文字列・数値・
67
- * 配列それぞれの定番で、毎日書くのはこの範囲だ、という主張がこの名前である。
64
+ * Not called "common", because that name says nothing — and lint bans it. It
65
+ * holds presence plus the everyday string, number and array checks, and the
66
+ * name is the claim that this is the range people write day to day.
68
67
  *
69
- * これでも「全部入り」ではない。全部入りが要るなら `@maroonedog/luq/plugins`
70
- * のバレルがあり、そちらは 77 個ぶん、gzip で +17,986 B を払う。
68
+ * Still not everything. For everything there is the `@maroonedog/luq/plugins`
69
+ * barrel, which costs accordingly.
71
70
  */
72
71
  export const everydayRules = Object.freeze({
73
72
  ...presence,
@@ -60,13 +60,11 @@ function createSubjectComposer(template) {
60
60
  return (siblings, value) => mergeOntoSiblings(siblings, nest(value));
61
61
  }
62
62
  /**
63
- * テンプレートを **一度だけ** 歩いて、包む関数に畳んでおく。
63
+ * Walks the template **once** and folds it into a wrapping function.
64
64
  *
65
- * 以前はここが `nestValue(template, 0, value)` で、検証のたびにテンプレートを
66
- * 歩き直して `segment.kind` を読み直していた。src/compile/validation-plan.types.ts
67
- * が書いているとおり「実行時はルールが何であるかを決め直してはならない。
68
- * 決めるのはコンパイルが済ませたこと」であり、ここはその例外になっていた。
69
- * 非ワイルドカードの経路 (createValueWriter) は最初からこの形である。
65
+ * Walking it per validation re-read each segment's kind every time, which is
66
+ * exactly the thing validation time must not do: what something IS was settled
67
+ * at compile time. The non-wildcard route was always shaped this way.
70
68
  */
71
69
  function compileNester(template) {
72
70
  let nest = (value) => value;
@@ -57,13 +57,11 @@ function createSubjectComposer(template) {
57
57
  return (siblings, value) => mergeOntoSiblings(siblings, nest(value));
58
58
  }
59
59
  /**
60
- * テンプレートを **一度だけ** 歩いて、包む関数に畳んでおく。
60
+ * Walks the template **once** and folds it into a wrapping function.
61
61
  *
62
- * 以前はここが `nestValue(template, 0, value)` で、検証のたびにテンプレートを
63
- * 歩き直して `segment.kind` を読み直していた。src/compile/validation-plan.types.ts
64
- * が書いているとおり「実行時はルールが何であるかを決め直してはならない。
65
- * 決めるのはコンパイルが済ませたこと」であり、ここはその例外になっていた。
66
- * 非ワイルドカードの経路 (createValueWriter) は最初からこの形である。
62
+ * Walking it per validation re-read each segment's kind every time, which is
63
+ * exactly the thing validation time must not do: what something IS was settled
64
+ * at compile time. The non-wildcard route was always shaped this way.
67
65
  */
68
66
  function compileNester(template) {
69
67
  let nest = (value) => value;