@maroonedog/luq 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +269 -52
- package/dist/builder/builder-surface.types.d.ts +1 -0
- package/dist/builder/create-builder.js +9 -0
- package/dist/builder/create-builder.mjs +9 -0
- package/dist/builder/field-builder.types.d.ts +13 -0
- package/dist/chain/bundle-paths.types.d.ts +26 -0
- package/dist/chain/bundle-paths.types.js +2 -0
- package/dist/chain/bundle-paths.types.mjs +1 -0
- package/dist/chain/chain-method.types.d.ts +8 -3
- package/dist/chain/resolve-args.types.d.ts +4 -2
- package/dist/compile/compile-array-node.d.ts +0 -7
- package/dist/compile/compile-array-node.js +4 -0
- package/dist/compile/compile-array-node.mjs +4 -0
- package/dist/compile/compile-field.js +10 -1
- package/dist/compile/compile-field.mjs +10 -1
- package/dist/compile/split-rules-by-kind.js +31 -7
- package/dist/compile/split-rules-by-kind.mjs +31 -7
- package/dist/compile/validation-plan.types.d.ts +23 -0
- package/dist/json-schema/flatten-schema.js +1 -1
- package/dist/json-schema/flatten-schema.mjs +1 -1
- package/dist/plugin-kit/marker.types.d.ts +18 -0
- package/dist/plugins/index.generated.d.ts +1 -0
- package/dist/plugins/index.generated.js +4 -2
- package/dist/plugins/index.generated.mjs +1 -0
- package/dist/plugins/manifest.generated.js +1 -0
- package/dist/plugins/manifest.generated.mjs +1 -0
- package/dist/plugins/stitch/stitch.d.ts +28 -8
- package/dist/plugins/stitch-with/index.d.ts +2 -0
- package/dist/plugins/stitch-with/index.js +5 -0
- package/dist/plugins/stitch-with/index.mjs +1 -0
- package/dist/plugins/stitch-with/stitch-with.d.ts +12 -0
- package/dist/plugins/stitch-with/stitch-with.js +94 -0
- package/dist/plugins/stitch-with/stitch-with.mjs +91 -0
- package/dist/plugins/stitchWith.d.ts +1 -0
- package/dist/plugins/stitchWith.js +2 -0
- package/dist/plugins/stitchWith.mjs +1 -0
- package/dist/plugins/string-min/string-min.js +21 -3
- package/dist/plugins/string-min/string-min.mjs +22 -4
- package/dist/presets/index.d.ts +1 -0
- package/dist/presets/index.js +9 -0
- package/dist/presets/index.mjs +1 -0
- package/dist/presets/presets.d.ts +165 -0
- package/dist/presets/presets.js +80 -0
- package/dist/presets/presets.mjs +77 -0
- package/dist/runtime/create-field-validator.js +24 -8
- package/dist/runtime/create-field-validator.mjs +24 -8
- package/dist/runtime/create-validator.js +38 -8
- package/dist/runtime/create-validator.mjs +38 -8
- package/dist/runtime/field-rule-context.d.ts +32 -0
- package/dist/runtime/field-rule-context.js +48 -0
- package/dist/runtime/field-rule-context.mjs +44 -0
- package/dist/runtime/index-stack.d.ts +29 -4
- package/dist/runtime/index-stack.js +76 -15
- package/dist/runtime/index-stack.mjs +76 -15
- package/dist/runtime/run-array-node.js +22 -10
- package/dist/runtime/run-array-node.mjs +22 -10
- package/dist/runtime/run-field.js +47 -17
- package/dist/runtime/run-field.mjs +47 -17
- package/dist/runtime/run-plan.js +5 -1
- package/dist/runtime/run-plan.mjs +5 -1
- package/dist/types/index.d.ts +12 -0
- package/package.json +35 -19
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { createIssue } from "./create-issue.mjs";
|
|
2
|
+
import { FieldRuleContext } from "./field-rule-context.mjs";
|
|
2
3
|
import { decidePresence } from "./decide-presence.mjs";
|
|
3
4
|
/** Shared, frozen, never re-assigned: the common answer allocates nothing. */
|
|
4
5
|
export const FIELD_VALUE_UNCHANGED = Object.freeze({
|
|
5
6
|
hasWriteBack: false,
|
|
6
7
|
});
|
|
7
8
|
export function runField(field, subject, context) {
|
|
8
|
-
const
|
|
9
|
-
const ruleContext = {
|
|
10
|
-
root: context.root,
|
|
11
|
-
path,
|
|
12
|
-
item: context.item,
|
|
13
|
-
external: context.external,
|
|
14
|
-
};
|
|
9
|
+
const ruleContext = new FieldRuleContext(context.root, context.indices, field.renderedPath, context.item, context.external);
|
|
15
10
|
const read = field.read(subject);
|
|
16
11
|
const value = applyDefault(field, read, context.root);
|
|
17
12
|
if (!decidePresence(field, value, ruleContext, context.sink)) {
|
|
@@ -43,24 +38,55 @@ function applyDefault(field, value, root) {
|
|
|
43
38
|
}
|
|
44
39
|
/** A closed gate ends the field successfully: no check, no transform. */
|
|
45
40
|
function openGates(field, value, ruleContext) {
|
|
46
|
-
for
|
|
41
|
+
// 添字ループである。for-of ではない。ここが回るのはコンパイル済みの
|
|
42
|
+
// 凍結配列で、凍結配列は V8 では PACKED_FROZEN_ELEMENTS になり、配列
|
|
43
|
+
// イテレータの高速化パスから外れる — イテレータと IteratorResult が
|
|
44
|
+
// 消去されず、要素×フィールドの回数だけ確保される。配列シェイプでは
|
|
45
|
+
// それだけで全ゴミの 45〜54% を占めていた (独立に5通りの改変で -45%
|
|
46
|
+
// 〜 -54%)。凍結は落とさない: コンパイル層の不変条件であり、凍結を
|
|
47
|
+
// 外しても添字ループより速くはならない。
|
|
48
|
+
const gates = field.gates;
|
|
49
|
+
for (let i = 0; i < gates.length; i += 1) {
|
|
50
|
+
const gate = gates[i];
|
|
51
|
+
if (gate === undefined)
|
|
52
|
+
continue;
|
|
47
53
|
if (!gate.shouldRun(value, ruleContext))
|
|
48
54
|
return false;
|
|
49
55
|
}
|
|
50
56
|
return true;
|
|
51
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* 失敗したときだけ通る側。ループ本体から出してある。
|
|
60
|
+
*
|
|
61
|
+
* runChecks はバイトコードで 302 バイトあり、TurboFan の呼び出し先
|
|
62
|
+
* インライン予算 (既定で累計 920 バイト) の最大の落選候補として
|
|
63
|
+
* --trace-turbo-inlining に名指しされていた。その 302 バイトの大半が、
|
|
64
|
+
* 受理された値では一度も走らない issue の組み立てである。ここへ出すと
|
|
65
|
+
* 残るループ本体が縮み、受理パスで 6.4% 速くなった。
|
|
66
|
+
*
|
|
67
|
+
* 中断の判定はここに含めない。issue を足したあとに shouldStopField を
|
|
68
|
+
* 見るという順序が abortEarlyOnEachField の意味そのものなので、呼び出し側に
|
|
69
|
+
* 並べて置いておく。
|
|
70
|
+
*/
|
|
71
|
+
function reportCheckFailure(check, detail, value, ruleContext, context) {
|
|
72
|
+
context.sink.add(createIssue({
|
|
73
|
+
path: ruleContext.path,
|
|
74
|
+
code: check.code,
|
|
75
|
+
severity: check.severity,
|
|
76
|
+
value,
|
|
77
|
+
render: (ctx) => check.describe(detail, ctx),
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
52
80
|
function runChecks(field, value, ruleContext, context, mark) {
|
|
53
|
-
|
|
81
|
+
const checks = field.checks;
|
|
82
|
+
for (let i = 0; i < checks.length; i += 1) {
|
|
83
|
+
const check = checks[i];
|
|
84
|
+
if (check === undefined)
|
|
85
|
+
continue;
|
|
54
86
|
const outcome = check.run(value, ruleContext);
|
|
55
87
|
if (outcome.ok)
|
|
56
88
|
continue;
|
|
57
|
-
context
|
|
58
|
-
path: ruleContext.path,
|
|
59
|
-
code: check.code,
|
|
60
|
-
severity: check.severity,
|
|
61
|
-
value,
|
|
62
|
-
render: (ctx) => check.describe(outcome.detail, ctx),
|
|
63
|
-
}));
|
|
89
|
+
reportCheckFailure(check, outcome.detail, value, ruleContext, context);
|
|
64
90
|
if (context.sink.shouldStopField(mark))
|
|
65
91
|
return;
|
|
66
92
|
}
|
|
@@ -71,7 +97,11 @@ function runTransforms(field, value, ruleContext, context, mark) {
|
|
|
71
97
|
return value;
|
|
72
98
|
}
|
|
73
99
|
let current = value;
|
|
74
|
-
|
|
100
|
+
const transforms = field.transforms;
|
|
101
|
+
for (let i = 0; i < transforms.length; i += 1) {
|
|
102
|
+
const transform = transforms[i];
|
|
103
|
+
if (transform === undefined)
|
|
104
|
+
continue;
|
|
75
105
|
current = transform.apply(current, ruleContext);
|
|
76
106
|
}
|
|
77
107
|
return current;
|
package/dist/runtime/run-plan.js
CHANGED
|
@@ -19,7 +19,11 @@ const output_writer_1 = require("./output-writer");
|
|
|
19
19
|
*/
|
|
20
20
|
function runPlan(plan, subject, context, targets = output_writer_1.NO_WRITE_TARGETS) {
|
|
21
21
|
let current = subject;
|
|
22
|
-
|
|
22
|
+
const fields = plan.fields;
|
|
23
|
+
for (let i = 0; i < fields.length; i += 1) {
|
|
24
|
+
const field = fields[i];
|
|
25
|
+
if (field === undefined)
|
|
26
|
+
continue;
|
|
23
27
|
const outcome = (0, run_field_1.runField)(field, current, context);
|
|
24
28
|
current = (0, output_writer_1.writeFieldValue)(field, current, outcome, context.shouldApplyTransforms);
|
|
25
29
|
if (context.sink.shouldStopPlan())
|
|
@@ -15,7 +15,11 @@ import { NO_WRITE_TARGETS, writeFieldValue } from "./output-writer.mjs";
|
|
|
15
15
|
*/
|
|
16
16
|
export function runPlan(plan, subject, context, targets = NO_WRITE_TARGETS) {
|
|
17
17
|
let current = subject;
|
|
18
|
-
|
|
18
|
+
const fields = plan.fields;
|
|
19
|
+
for (let i = 0; i < fields.length; i += 1) {
|
|
20
|
+
const field = fields[i];
|
|
21
|
+
if (field === undefined)
|
|
22
|
+
continue;
|
|
19
23
|
const outcome = runField(field, current, context);
|
|
20
24
|
current = writeFieldValue(field, current, outcome, context.shouldApplyTransforms);
|
|
21
25
|
if (context.sink.shouldStopPlan())
|
package/dist/types/index.d.ts
CHANGED
|
@@ -43,6 +43,18 @@ export type CheckOutcome = {
|
|
|
43
43
|
};
|
|
44
44
|
export declare const PASS: CheckOutcome;
|
|
45
45
|
export declare function fail(detail: IssueDetail): CheckOutcome;
|
|
46
|
+
/**
|
|
47
|
+
* クロスフィールドの判定が返せるもの。真偽だけでも、メッセージ付きでもよい。
|
|
48
|
+
*
|
|
49
|
+
* ここ (L0) にあるのは、チェーン層が `stitch` の呼び出し側の型を組むときに
|
|
50
|
+
* 参照するからである。プラグイン (L7) に置いたままだと L3 -> L7 の import に
|
|
51
|
+
* なり、層が逆流する。プラグイン側の `StitchOutcome` はこれの別名で、
|
|
52
|
+
* 公開名は変えていない。
|
|
53
|
+
*/
|
|
54
|
+
export interface CrossFieldOutcome {
|
|
55
|
+
readonly valid: boolean;
|
|
56
|
+
readonly message?: string;
|
|
57
|
+
}
|
|
46
58
|
export interface ArrayItemContext {
|
|
47
59
|
readonly index: number;
|
|
48
60
|
readonly item: unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maroonedog/luq",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Universal Model & API Definition Platform - TypeScript validation library evolving into cross-language code generation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -37,6 +37,11 @@
|
|
|
37
37
|
"import": "./dist/standard-schema.mjs",
|
|
38
38
|
"require": "./dist/standard-schema.js"
|
|
39
39
|
},
|
|
40
|
+
"./presets": {
|
|
41
|
+
"types": "./dist/presets/index.d.ts",
|
|
42
|
+
"import": "./dist/presets/index.mjs",
|
|
43
|
+
"require": "./dist/presets/index.js"
|
|
44
|
+
},
|
|
40
45
|
"./plugins": {
|
|
41
46
|
"types": "./dist/plugins/index.d.ts",
|
|
42
47
|
"import": "./dist/plugins/index.mjs",
|
|
@@ -252,6 +257,11 @@
|
|
|
252
257
|
"import": "./dist/plugins/stitch.mjs",
|
|
253
258
|
"require": "./dist/plugins/stitch.js"
|
|
254
259
|
},
|
|
260
|
+
"./plugins/stitchWith": {
|
|
261
|
+
"types": "./dist/plugins/stitchWith.d.ts",
|
|
262
|
+
"import": "./dist/plugins/stitchWith.mjs",
|
|
263
|
+
"require": "./dist/plugins/stitchWith.js"
|
|
264
|
+
},
|
|
255
265
|
"./plugins/stringAlphanumeric": {
|
|
256
266
|
"types": "./dist/plugins/stringAlphanumeric.d.ts",
|
|
257
267
|
"import": "./dist/plugins/stringAlphanumeric.mjs",
|
|
@@ -432,14 +442,14 @@
|
|
|
432
442
|
"build": "npx ts-node --project scripts/tsconfig.json scripts/build.ts",
|
|
433
443
|
"test": "jest --no-watch --no-watchman --passWithNoTests",
|
|
434
444
|
"test:watch": "jest --watch",
|
|
435
|
-
"lint": "
|
|
445
|
+
"lint": "npm run lint:ox && npm run lint:naming",
|
|
436
446
|
"prepare": "npm run build",
|
|
437
447
|
"prepublishOnly": "npm run verify",
|
|
438
448
|
"generate-docs": "npx ts-node --project scripts/tsconfig.json scripts/generate-docs.ts",
|
|
439
|
-
"lint:fix": "
|
|
449
|
+
"lint:fix": "oxlint -c .oxlintrc.json --fix src bench",
|
|
440
450
|
"lint:filenames": "node scripts/check-filenames.js",
|
|
441
|
-
"format": "
|
|
442
|
-
"format:check": "
|
|
451
|
+
"format": "oxfmt src test scripts bench",
|
|
452
|
+
"format:check": "oxfmt --check src test scripts bench",
|
|
443
453
|
"typecheck": "npm run typecheck:src && npm run typecheck:scripts && npm run typecheck:bench",
|
|
444
454
|
"typecheck:src": "tsc --noEmit -p tsconfig.json",
|
|
445
455
|
"typecheck:scripts": "tsc --noEmit -p scripts/tsconfig.json",
|
|
@@ -470,10 +480,16 @@
|
|
|
470
480
|
"check:doc-examples": "npx ts-node --project scripts/tsconfig.json scripts/check-doc-examples.ts",
|
|
471
481
|
"check:doc-imports": "npx ts-node --project scripts/tsconfig.json scripts/check-doc-imports.ts",
|
|
472
482
|
"check:generated-docs": "npx ts-node --project scripts/tsconfig.json scripts/generate-docs.ts --check",
|
|
473
|
-
"check:docs": "npm run check:generated-docs && npm run check:doc-examples && npm run check:doc-imports && npm run check:conformance-figures",
|
|
483
|
+
"check:docs": "npm run check:generated-docs && npm run check:doc-examples && npm run check:doc-imports && npm run check:conformance-figures && npm run check:perf-figures",
|
|
474
484
|
"bench:record": "npx ts-node --project scripts/tsconfig.json scripts/run-bench.ts --record",
|
|
475
485
|
"bench:gate": "npx ts-node --project scripts/tsconfig.json scripts/run-bench.ts --gate",
|
|
476
|
-
"check:conformance-figures": "npx ts-node --project scripts/tsconfig.json scripts/check-conformance-figures.ts"
|
|
486
|
+
"check:conformance-figures": "npx ts-node --project scripts/tsconfig.json scripts/check-conformance-figures.ts",
|
|
487
|
+
"bench:competitors": "npx ts-node --project bench/tsconfig.json bench/competitors/report-competitors.ts",
|
|
488
|
+
"bench:competitors:check": "npx ts-node --project bench/tsconfig.json bench/competitors/check-competitors.ts",
|
|
489
|
+
"lint:ox": "oxlint -c .oxlintrc.json src bench",
|
|
490
|
+
"lint:naming": "eslint \"src/**/*.ts\" \"bench/**/*.ts\"",
|
|
491
|
+
"generate:perf-figures": "npx ts-node --project scripts/tsconfig.json scripts/check-perf-figures.ts --write",
|
|
492
|
+
"check:perf-figures": "npx ts-node --project scripts/tsconfig.json scripts/check-perf-figures.ts"
|
|
477
493
|
},
|
|
478
494
|
"repository": {
|
|
479
495
|
"type": "git",
|
|
@@ -495,28 +511,28 @@
|
|
|
495
511
|
"files": [
|
|
496
512
|
"dist"
|
|
497
513
|
],
|
|
514
|
+
"publishConfig": {
|
|
515
|
+
"access": "public",
|
|
516
|
+
"provenance": true
|
|
517
|
+
},
|
|
498
518
|
"devDependencies": {
|
|
499
|
-
"@playwright/test": "^1.54.2",
|
|
500
519
|
"@standard-schema/spec": "^1.1.0",
|
|
501
|
-
"@swc/cli": "^0.4.0",
|
|
502
|
-
"@swc/core": "^1.7.36",
|
|
503
|
-
"@swc/jest": "^0.2.36",
|
|
504
520
|
"@types/jest": "^29.5.14",
|
|
505
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
506
|
-
"@typescript-eslint/parser": "^
|
|
507
|
-
"
|
|
521
|
+
"@typescript-eslint/eslint-plugin": "^8.70.0",
|
|
522
|
+
"@typescript-eslint/parser": "^8.70.0",
|
|
523
|
+
"ajv": "^8.20.0",
|
|
524
|
+
"ajv-formats": "^3.0.1",
|
|
508
525
|
"esbuild": "^0.25.5",
|
|
509
526
|
"eslint": "^8.57.1",
|
|
510
|
-
"expect-type": "^1.4.0",
|
|
511
527
|
"jest": "^29.7.0",
|
|
512
|
-
"
|
|
513
|
-
"
|
|
514
|
-
"rollup-plugin-dts": "^6.2.1",
|
|
515
|
-
"sharp": "^0.34.3",
|
|
528
|
+
"oxfmt": "^0.67.0",
|
|
529
|
+
"oxlint": "^1.82.0",
|
|
516
530
|
"ts-jest": "^29.4.0",
|
|
517
531
|
"ts-node": "^10.9.2",
|
|
518
532
|
"tsx": "^4.20.3",
|
|
519
533
|
"typescript": "^5.8.3",
|
|
534
|
+
"valibot": "^1.4.2",
|
|
535
|
+
"yup": "^1.7.1",
|
|
520
536
|
"zod": "^4.0.14"
|
|
521
537
|
},
|
|
522
538
|
"sideEffects": false
|