@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.
- package/README.md +47 -602
- package/dist/builder/compile-declarations.d.ts +7 -1
- package/dist/builder/compile-declarations.js +18 -8
- package/dist/builder/compile-declarations.mjs +18 -8
- package/dist/builder/create-builder.js +2 -3
- package/dist/builder/create-builder.mjs +2 -3
- package/dist/builder/create-field-builder.js +13 -1
- package/dist/builder/create-field-builder.mjs +13 -1
- package/dist/builder/declared-calls-store.d.ts +9 -0
- package/dist/builder/declared-calls-store.js +19 -0
- package/dist/builder/declared-calls-store.mjs +15 -0
- package/dist/builder/field-declared-calls.types.d.ts +6 -0
- package/dist/builder/field-declared-calls.types.js +2 -0
- package/dist/builder/field-declared-calls.types.mjs +1 -0
- package/dist/builder/field-entry.types.d.ts +9 -3
- package/dist/builder/field-options.types.d.ts +26 -0
- package/dist/chain/bundle-paths.types.d.ts +9 -12
- package/dist/chain/chain-node-store.d.ts +5 -0
- package/dist/chain/chain-node-store.js +15 -0
- package/dist/chain/chain-node-store.mjs +11 -0
- package/dist/chain/collect-field-rules.d.ts +13 -2
- package/dist/chain/collect-field-rules.js +10 -3
- package/dist/chain/collect-field-rules.mjs +10 -3
- package/dist/chain/create-chain-node.d.ts +10 -0
- package/dist/chain/create-chain-node.js +19 -9
- package/dist/chain/create-chain-node.mjs +19 -9
- package/dist/chain/create-field-slots.js +9 -1
- package/dist/chain/create-field-slots.mjs +9 -1
- package/dist/chain/declaration-recorder.port.d.ts +31 -0
- package/dist/chain/declaration-recorder.port.js +17 -0
- package/dist/chain/declaration-recorder.port.mjs +13 -0
- package/dist/chain/declared-call.types.d.ts +15 -0
- package/dist/chain/declared-call.types.js +2 -0
- package/dist/chain/declared-call.types.mjs +1 -0
- package/dist/chain/index.d.ts +3 -1
- package/dist/chain/slot-type-guard.d.ts +10 -0
- package/dist/chain/slot-type-guard.js +37 -0
- package/dist/chain/slot-type-guard.mjs +34 -0
- package/dist/compile/compile-array-node.js +1 -0
- package/dist/compile/compile-array-node.mjs +1 -0
- package/dist/compile/compile-field.d.ts +1 -0
- package/dist/compile/compile-field.js +8 -6
- package/dist/compile/compile-field.mjs +8 -6
- package/dist/compile/compile-schema.js +4 -0
- package/dist/compile/compile-schema.mjs +4 -0
- package/dist/compile/group-array-fields.d.ts +1 -0
- package/dist/compile/split-rules-by-kind.js +10 -14
- package/dist/compile/split-rules-by-kind.mjs +10 -14
- package/dist/compile/validation-plan.types.d.ts +19 -6
- package/dist/core/type-erasure.d.ts +36 -30
- package/dist/core/type-erasure.js +36 -30
- package/dist/core/type-erasure.mjs +36 -30
- package/dist/json-schema/build-from-schema.js +8 -1
- package/dist/json-schema/build-from-schema.mjs +8 -1
- package/dist/json-schema/create-structural-context.js +3 -0
- package/dist/json-schema/create-structural-context.mjs +3 -0
- package/dist/json-schema/declare-additional-properties.d.ts +7 -7
- package/dist/json-schema/declare-additional-properties.js +7 -7
- package/dist/json-schema/declare-additional-properties.mjs +7 -7
- package/dist/json-schema/declare-object-keywords.js +4 -4
- package/dist/json-schema/declare-object-keywords.mjs +4 -4
- package/dist/json-schema/follow-json-pointer.d.ts +7 -6
- package/dist/json-schema/follow-json-pointer.js +24 -24
- package/dist/json-schema/follow-json-pointer.mjs +24 -24
- package/dist/json-schema/ref-resolution-error.js +3 -3
- package/dist/json-schema/ref-resolution-error.mjs +3 -3
- package/dist/json-schema/schema-registry.js +12 -11
- package/dist/json-schema/schema-registry.mjs +12 -11
- package/dist/json-schema/uri-reference.js +12 -12
- package/dist/json-schema/uri-reference.mjs +12 -12
- package/dist/path/create-value-writer.js +12 -12
- package/dist/path/create-value-writer.mjs +12 -12
- package/dist/path/reserved-segment.d.ts +16 -16
- package/dist/path/reserved-segment.js +17 -21
- package/dist/path/reserved-segment.mjs +17 -21
- package/dist/plugins/index.generated.js +2 -2
- package/dist/plugins/index.generated.mjs +2 -2
- package/dist/plugins/manifest.generated.js +2 -2
- package/dist/plugins/manifest.generated.mjs +2 -2
- package/dist/plugins/object/object.d.ts +6 -0
- package/dist/plugins/object/object.js +9 -11
- package/dist/plugins/object/object.mjs +10 -12
- package/dist/plugins/object-additional-properties/select-additional-keys.d.ts +8 -8
- package/dist/plugins/object-additional-properties/select-additional-keys.js +16 -16
- package/dist/plugins/object-additional-properties/select-additional-keys.mjs +16 -16
- package/dist/plugins/stitch/stitch.d.ts +10 -14
- package/dist/plugins/stitch-with/stitch-with.d.ts +1 -1
- package/dist/plugins/stitch-with/stitch-with.js +22 -24
- package/dist/plugins/stitch-with/stitch-with.mjs +22 -24
- package/dist/plugins/string-min/string-min.js +6 -8
- package/dist/plugins/string-min/string-min.mjs +6 -8
- package/dist/presets/presets.d.ts +10 -11
- package/dist/presets/presets.js +22 -23
- package/dist/presets/presets.mjs +22 -23
- package/dist/runtime/create-field-validator.js +4 -6
- package/dist/runtime/create-field-validator.mjs +4 -6
- package/dist/runtime/create-validator.js +11 -11
- package/dist/runtime/create-validator.mjs +11 -11
- package/dist/runtime/output-writer.js +5 -1
- package/dist/runtime/output-writer.mjs +5 -1
- package/dist/runtime/run-array-node.js +6 -6
- package/dist/runtime/run-array-node.mjs +6 -6
- package/dist/runtime/run-field.js +18 -19
- package/dist/runtime/run-field.mjs +18 -19
- package/dist/standard-schema/assemble-json-schema.d.ts +4 -0
- package/dist/standard-schema/assemble-json-schema.js +95 -0
- package/dist/standard-schema/assemble-json-schema.mjs +92 -0
- package/dist/standard-schema/declaration-recorder.d.ts +6 -0
- package/dist/standard-schema/declaration-recorder.js +30 -0
- package/dist/standard-schema/declaration-recorder.mjs +27 -0
- package/dist/standard-schema/declarations-unavailable-error.d.ts +4 -0
- package/dist/standard-schema/declarations-unavailable-error.js +32 -0
- package/dist/standard-schema/declarations-unavailable-error.mjs +28 -0
- package/dist/standard-schema/emit-field-schema.d.ts +9 -0
- package/dist/standard-schema/emit-field-schema.js +68 -0
- package/dist/standard-schema/emit-field-schema.mjs +65 -0
- package/dist/standard-schema/index.d.ts +5 -0
- package/dist/standard-schema/index.js +9 -1
- package/dist/standard-schema/index.mjs +4 -0
- package/dist/standard-schema/json-schema-target.d.ts +6 -0
- package/dist/standard-schema/json-schema-target.js +44 -0
- package/dist/standard-schema/json-schema-target.mjs +39 -0
- package/dist/standard-schema/plugin-keyword-map.d.ts +3 -0
- package/dist/standard-schema/plugin-keyword-map.js +93 -0
- package/dist/standard-schema/plugin-keyword-map.mjs +90 -0
- package/dist/standard-schema/split-issue-path.d.ts +6 -4
- package/dist/standard-schema/split-issue-path.js +15 -13
- package/dist/standard-schema/split-issue-path.mjs +15 -13
- package/dist/standard-schema/standard-schema.types.d.ts +8 -7
- package/dist/standard-schema/standard-schema.types.js +6 -6
- package/dist/standard-schema/standard-schema.types.mjs +6 -6
- package/dist/standard-schema/to-standard-json-schema.d.ts +19 -0
- package/dist/standard-schema/to-standard-json-schema.js +36 -0
- package/dist/standard-schema/to-standard-json-schema.mjs +33 -0
- package/dist/standard-schema/to-standard-schema.d.ts +16 -15
- package/dist/standard-schema/to-standard-schema.js +15 -22
- package/dist/standard-schema/to-standard-schema.mjs +15 -22
- package/dist/standard-schema/unrepresentable-rule-error.d.ts +15 -0
- package/dist/standard-schema/unrepresentable-rule-error.js +43 -0
- package/dist/standard-schema/unrepresentable-rule-error.mjs +38 -0
- package/dist/types/index.d.ts +12 -12
- package/dist/types/index.js +7 -7
- package/dist/types/index.mjs +7 -7
- 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
|
-
//
|
|
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
|
|
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
|
-
*
|
|
14
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
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
|
-
*
|
|
30
|
+
* The shape build() receives at run time. **Not the type a caller sees.**
|
|
32
31
|
*
|
|
33
|
-
* `.stitch(["price", "quantity"], ...)`
|
|
34
|
-
*
|
|
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
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
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
|
-
//
|
|
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`
|
|
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
|
-
//
|
|
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
|
-
//
|
|
31
|
-
// `readonly Rule[]`
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
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
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
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
|
-
//
|
|
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`
|
|
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
|
-
//
|
|
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
|
-
//
|
|
28
|
-
// `readonly Rule[]`
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
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
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
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
|
|
35
|
-
//
|
|
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
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
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
|
|
32
|
-
//
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
85
|
+
* The four bundles above, together.
|
|
87
86
|
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
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
|
-
*
|
|
93
|
-
*
|
|
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"], {
|
package/dist/presets/presets.js
CHANGED
|
@@ -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
|
-
//
|
|
8
|
-
//
|
|
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
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
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
|
-
//
|
|
18
|
-
//
|
|
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
|
-
//
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
65
|
+
* The four bundles above, together.
|
|
67
66
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
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
|
-
*
|
|
73
|
-
*
|
|
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,
|
package/dist/presets/presets.mjs
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
// ===========================================================================
|
|
2
|
-
// L7 src/presets/presets.ts —
|
|
2
|
+
// L7 src/presets/presets.ts — predefined plugin bundles.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
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
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
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
|
-
//
|
|
15
|
-
//
|
|
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
|
-
//
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
62
|
+
* The four bundles above, together.
|
|
64
63
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
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
|
-
*
|
|
70
|
-
*
|
|
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
|
-
*
|
|
66
|
-
*
|
|
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
|
-
*
|
|
63
|
-
*
|
|
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;
|