@drzl/validation-core 3.22.2 → 3.22.3

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/dist/index.cjs CHANGED
@@ -55,6 +55,7 @@ __export(index_exports, {
55
55
  canonicalMembers: () => canonicalMembers,
56
56
  canonicalNumericText: () => canonicalNumericText,
57
57
  classifyTableChecks: () => classifyTableChecks,
58
+ codePointCompare: () => codePointCompare,
58
59
  columnMetaFacts: () => columnMetaFacts,
59
60
  comparisonWire: () => comparisonWire,
60
61
  describeSet: () => describeSet,
@@ -67,6 +68,7 @@ __export(index_exports, {
67
68
  isProjectInstallPath: () => isProjectInstallPath,
68
69
  lengthCheckLabel: () => lengthCheckLabel,
69
70
  lengthMeasure: () => lengthMeasure,
71
+ measureCompare: () => measureCompare,
70
72
  measureExpression: () => measureExpression,
71
73
  moduleFileName: () => moduleFileName,
72
74
  moduleSpecifier: () => moduleSpecifier,
@@ -112,6 +114,34 @@ function lengthMeasure(column, check) {
112
114
  if (column.tsType !== "string") return void 0;
113
115
  return check.unit === "bytes" ? "utf8Bytes" : "codePoints";
114
116
  }
117
+ function codePointCompare(variable, operator, bound) {
118
+ const units = `${variable}.length`;
119
+ const spread2 = `[...${variable}].length`;
120
+ switch (operator) {
121
+ case "<=":
122
+ case "<":
123
+ return `(${units} ${operator} ${bound} || ${spread2} ${operator} ${bound})`;
124
+ case ">=":
125
+ case ">":
126
+ return `(${units} ${operator} ${bound} && ${spread2} ${operator} ${bound})`;
127
+ case "===":
128
+ return `(${units} >= ${bound} && ${spread2} === ${bound})`;
129
+ case "!==":
130
+ return `(${units} < ${bound} || ${spread2} !== ${bound})`;
131
+ }
132
+ }
133
+ function measureCompare(measure, variable, operator, bound) {
134
+ const js = {
135
+ ">=": ">=",
136
+ ">": ">",
137
+ "<=": "<=",
138
+ "<": "<",
139
+ "=": "===",
140
+ "<>": "!=="
141
+ }[operator];
142
+ if (measure === "codePoints") return codePointCompare(variable, js, bound);
143
+ return `${measureExpression(measure, variable)} ${js} ${bound}`;
144
+ }
115
145
  function measureExpression(measure, variable) {
116
146
  switch (measure) {
117
147
  case "codePoints":
@@ -1944,6 +1974,7 @@ async function formatCode(code, filePath, fmt) {
1944
1974
  canonicalMembers,
1945
1975
  canonicalNumericText,
1946
1976
  classifyTableChecks,
1977
+ codePointCompare,
1947
1978
  columnMetaFacts,
1948
1979
  comparisonWire,
1949
1980
  describeSet,
@@ -1956,6 +1987,7 @@ async function formatCode(code, filePath, fmt) {
1956
1987
  isProjectInstallPath,
1957
1988
  lengthCheckLabel,
1958
1989
  lengthMeasure,
1990
+ measureCompare,
1959
1991
  measureExpression,
1960
1992
  moduleFileName,
1961
1993
  moduleSpecifier,
package/dist/index.d.cts CHANGED
@@ -504,6 +504,35 @@ declare function lengthMeasure(column: {
504
504
  * TypeBox reach it off the row object as `o["blob"]`. `CODEPOINT_LENGTH` is the fixed-variable
505
505
  * spelling of the first arm and stays for the call sites that already use it.
506
506
  */
507
+ /**
508
+ * A code-point count compared against a bound, without spreading the string when it cannot matter.
509
+ *
510
+ * `[...v].length` allocates an array of code points, and it sits on the path every ordinary row
511
+ * takes. A UTF-16 unit count is free and is never *smaller* than a code-point count, since only a
512
+ * surrogate pair costs two units for one code point. That one fact settles every operator here:
513
+ *
514
+ * `<=`, `<` units within the bound means code points are too short-circuit to ACCEPT
515
+ * `>=`, `>` units under the bound means code points are too short-circuit to REJECT
516
+ * `===` units under the bound means code points cannot equal it short-circuit to REJECT
517
+ * `!==` units under the bound means code points cannot equal it short-circuit to ACCEPT
518
+ *
519
+ * So the spread runs only for a string long enough in units to be in doubt, which for a cap is the
520
+ * only string that was ever in doubt. Measured over a 20000-string random pool plus the awkward
521
+ * cases (emoji, combining marks, a lone surrogate, empty, CJK at the bound): the two forms answer
522
+ * identically on every one. Throughput on the check alone, cap 64: ordinary ASCII rows 23171k/s
523
+ * against 215029k/s, rows at the cap 4250k/s against 235657k/s.
524
+ *
525
+ * Only the code-point measurement is rewritten. A `byteLength` reads `v.length` already and has
526
+ * nothing to avoid, and the UTF-8 arm has its own sound short-circuits in both directions but a
527
+ * different allocation to weigh, so it is left for its own measurement rather than folded in here.
528
+ */
529
+ declare function codePointCompare(variable: string, operator: '>=' | '>' | '<=' | '<' | '===' | '!==', bound: string | number): string;
530
+ /**
531
+ * A length comparison over whichever measurement the column answers, short-circuited where that is
532
+ * sound. The one place an operator and a count meet, so no generator has to re-derive which
533
+ * rewrites are safe; see `codePointCompare`.
534
+ */
535
+ declare function measureCompare(measure: LengthMeasure, variable: string, operator: LengthCheck['operator'], bound: string | number): string;
507
536
  declare function measureExpression(measure: LengthMeasure, variable: string): string;
508
537
  /**
509
538
  * A count constraint as the sentence every emitted schema attaches and the ledger keys on.
@@ -1668,4 +1697,4 @@ declare function isProjectInstallPath(manifestPath: string): boolean;
1668
1697
  */
1669
1698
  declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
1670
1699
 
1671
- export { AFFIX_PREFIX_PATTERN, AFFIX_PROBE_TABLE, AFFIX_SUFFIX_PATTERN, type AffixIssue, type AffixOptions, type AffixValue, type BrandAlias, type BrandPlan, type BrandingOption, type BrandingOptions, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, CONSTRAINTS_MODULE, type CardinalityCheck, type CheckPart, type CheckPartPlace, type ClassifiedCheck, type ColumnCheck, type ColumnMetaFacts, type ColumnSet, type ComparisonWire, type ConstraintFacts, type ConstraintKind, type ConstraintsModuleOptions, type ConstraintsOption, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_NESTED_DEPTH, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FileSink, type FormatOptions, type GeneratorFs, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, type LengthMeasure, MAX_NESTED_DEPTH, type MetaFactOptions, NAME_MODES, NESTED_PREFIX, NUMERIC_CANON_NAME, NUMERIC_CANON_SOURCE, type NameMode, type NestedArm, type NestedMode, type NestedNode, type NullCheck, type ParsedCheck, type ResolvedAffix, type ResolvedBranding, type RowCheck, type Table, type TableCase, type TableConstraints, type TableMetaFacts, type TableMetaOptions, type UnenforcedLiteral, type UnenforcedPart, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, type WireLiteralFit, type WireLiteralQuestion, applyTableCase, applyWirePolicy, buildBrandPlan, buildNestedPlan, canonicalMembers, canonicalNumericText, classifyTableChecks, columnMetaFacts, comparisonWire, describeSet, fileWriter, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, isProjectInstallPath, lengthCheckLabel, lengthMeasure, measureExpression, moduleFileName, moduleSpecifier, needsNumericCanon, nestedArmNotes, nestedNodeColumns, nestedSchemaName, nestedTypeName, nonFiniteAccepted, nonFiniteRefused, parseCheck, parsesToADate, pascalCase, renderConstraintsModule, renderDuplicateFinder, resolveAffix, resolveBranding, resolveConfiguredImport, resolveConstraints, resolveNestedDepth, schemaName, selectColumns, tableConstraints, tableMetaFacts, typeName, updateColumns, validateAffix, wireLiteralFit, wireNumberLiteral };
1700
+ export { AFFIX_PREFIX_PATTERN, AFFIX_PROBE_TABLE, AFFIX_SUFFIX_PATTERN, type AffixIssue, type AffixOptions, type AffixValue, type BrandAlias, type BrandPlan, type BrandingOption, type BrandingOptions, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, CONSTRAINTS_MODULE, type CardinalityCheck, type CheckPart, type CheckPartPlace, type ClassifiedCheck, type ColumnCheck, type ColumnMetaFacts, type ColumnSet, type ComparisonWire, type ConstraintFacts, type ConstraintKind, type ConstraintsModuleOptions, type ConstraintsOption, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_NESTED_DEPTH, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FileSink, type FormatOptions, type GeneratorFs, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, type LengthMeasure, MAX_NESTED_DEPTH, type MetaFactOptions, NAME_MODES, NESTED_PREFIX, NUMERIC_CANON_NAME, NUMERIC_CANON_SOURCE, type NameMode, type NestedArm, type NestedMode, type NestedNode, type NullCheck, type ParsedCheck, type ResolvedAffix, type ResolvedBranding, type RowCheck, type Table, type TableCase, type TableConstraints, type TableMetaFacts, type TableMetaOptions, type UnenforcedLiteral, type UnenforcedPart, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, type WireLiteralFit, type WireLiteralQuestion, applyTableCase, applyWirePolicy, buildBrandPlan, buildNestedPlan, canonicalMembers, canonicalNumericText, classifyTableChecks, codePointCompare, columnMetaFacts, comparisonWire, describeSet, fileWriter, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, isProjectInstallPath, lengthCheckLabel, lengthMeasure, measureCompare, measureExpression, moduleFileName, moduleSpecifier, needsNumericCanon, nestedArmNotes, nestedNodeColumns, nestedSchemaName, nestedTypeName, nonFiniteAccepted, nonFiniteRefused, parseCheck, parsesToADate, pascalCase, renderConstraintsModule, renderDuplicateFinder, resolveAffix, resolveBranding, resolveConfiguredImport, resolveConstraints, resolveNestedDepth, schemaName, selectColumns, tableConstraints, tableMetaFacts, typeName, updateColumns, validateAffix, wireLiteralFit, wireNumberLiteral };
package/dist/index.d.ts CHANGED
@@ -504,6 +504,35 @@ declare function lengthMeasure(column: {
504
504
  * TypeBox reach it off the row object as `o["blob"]`. `CODEPOINT_LENGTH` is the fixed-variable
505
505
  * spelling of the first arm and stays for the call sites that already use it.
506
506
  */
507
+ /**
508
+ * A code-point count compared against a bound, without spreading the string when it cannot matter.
509
+ *
510
+ * `[...v].length` allocates an array of code points, and it sits on the path every ordinary row
511
+ * takes. A UTF-16 unit count is free and is never *smaller* than a code-point count, since only a
512
+ * surrogate pair costs two units for one code point. That one fact settles every operator here:
513
+ *
514
+ * `<=`, `<` units within the bound means code points are too short-circuit to ACCEPT
515
+ * `>=`, `>` units under the bound means code points are too short-circuit to REJECT
516
+ * `===` units under the bound means code points cannot equal it short-circuit to REJECT
517
+ * `!==` units under the bound means code points cannot equal it short-circuit to ACCEPT
518
+ *
519
+ * So the spread runs only for a string long enough in units to be in doubt, which for a cap is the
520
+ * only string that was ever in doubt. Measured over a 20000-string random pool plus the awkward
521
+ * cases (emoji, combining marks, a lone surrogate, empty, CJK at the bound): the two forms answer
522
+ * identically on every one. Throughput on the check alone, cap 64: ordinary ASCII rows 23171k/s
523
+ * against 215029k/s, rows at the cap 4250k/s against 235657k/s.
524
+ *
525
+ * Only the code-point measurement is rewritten. A `byteLength` reads `v.length` already and has
526
+ * nothing to avoid, and the UTF-8 arm has its own sound short-circuits in both directions but a
527
+ * different allocation to weigh, so it is left for its own measurement rather than folded in here.
528
+ */
529
+ declare function codePointCompare(variable: string, operator: '>=' | '>' | '<=' | '<' | '===' | '!==', bound: string | number): string;
530
+ /**
531
+ * A length comparison over whichever measurement the column answers, short-circuited where that is
532
+ * sound. The one place an operator and a count meet, so no generator has to re-derive which
533
+ * rewrites are safe; see `codePointCompare`.
534
+ */
535
+ declare function measureCompare(measure: LengthMeasure, variable: string, operator: LengthCheck['operator'], bound: string | number): string;
507
536
  declare function measureExpression(measure: LengthMeasure, variable: string): string;
508
537
  /**
509
538
  * A count constraint as the sentence every emitted schema attaches and the ledger keys on.
@@ -1668,4 +1697,4 @@ declare function isProjectInstallPath(manifestPath: string): boolean;
1668
1697
  */
1669
1698
  declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
1670
1699
 
1671
- export { AFFIX_PREFIX_PATTERN, AFFIX_PROBE_TABLE, AFFIX_SUFFIX_PATTERN, type AffixIssue, type AffixOptions, type AffixValue, type BrandAlias, type BrandPlan, type BrandingOption, type BrandingOptions, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, CONSTRAINTS_MODULE, type CardinalityCheck, type CheckPart, type CheckPartPlace, type ClassifiedCheck, type ColumnCheck, type ColumnMetaFacts, type ColumnSet, type ComparisonWire, type ConstraintFacts, type ConstraintKind, type ConstraintsModuleOptions, type ConstraintsOption, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_NESTED_DEPTH, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FileSink, type FormatOptions, type GeneratorFs, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, type LengthMeasure, MAX_NESTED_DEPTH, type MetaFactOptions, NAME_MODES, NESTED_PREFIX, NUMERIC_CANON_NAME, NUMERIC_CANON_SOURCE, type NameMode, type NestedArm, type NestedMode, type NestedNode, type NullCheck, type ParsedCheck, type ResolvedAffix, type ResolvedBranding, type RowCheck, type Table, type TableCase, type TableConstraints, type TableMetaFacts, type TableMetaOptions, type UnenforcedLiteral, type UnenforcedPart, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, type WireLiteralFit, type WireLiteralQuestion, applyTableCase, applyWirePolicy, buildBrandPlan, buildNestedPlan, canonicalMembers, canonicalNumericText, classifyTableChecks, columnMetaFacts, comparisonWire, describeSet, fileWriter, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, isProjectInstallPath, lengthCheckLabel, lengthMeasure, measureExpression, moduleFileName, moduleSpecifier, needsNumericCanon, nestedArmNotes, nestedNodeColumns, nestedSchemaName, nestedTypeName, nonFiniteAccepted, nonFiniteRefused, parseCheck, parsesToADate, pascalCase, renderConstraintsModule, renderDuplicateFinder, resolveAffix, resolveBranding, resolveConfiguredImport, resolveConstraints, resolveNestedDepth, schemaName, selectColumns, tableConstraints, tableMetaFacts, typeName, updateColumns, validateAffix, wireLiteralFit, wireNumberLiteral };
1700
+ export { AFFIX_PREFIX_PATTERN, AFFIX_PROBE_TABLE, AFFIX_SUFFIX_PATTERN, type AffixIssue, type AffixOptions, type AffixValue, type BrandAlias, type BrandPlan, type BrandingOption, type BrandingOptions, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, CONSTRAINTS_MODULE, type CardinalityCheck, type CheckPart, type CheckPartPlace, type ClassifiedCheck, type ColumnCheck, type ColumnMetaFacts, type ColumnSet, type ComparisonWire, type ConstraintFacts, type ConstraintKind, type ConstraintsModuleOptions, type ConstraintsOption, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_NESTED_DEPTH, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FileSink, type FormatOptions, type GeneratorFs, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, type LengthMeasure, MAX_NESTED_DEPTH, type MetaFactOptions, NAME_MODES, NESTED_PREFIX, NUMERIC_CANON_NAME, NUMERIC_CANON_SOURCE, type NameMode, type NestedArm, type NestedMode, type NestedNode, type NullCheck, type ParsedCheck, type ResolvedAffix, type ResolvedBranding, type RowCheck, type Table, type TableCase, type TableConstraints, type TableMetaFacts, type TableMetaOptions, type UnenforcedLiteral, type UnenforcedPart, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, type WireLiteralFit, type WireLiteralQuestion, applyTableCase, applyWirePolicy, buildBrandPlan, buildNestedPlan, canonicalMembers, canonicalNumericText, classifyTableChecks, codePointCompare, columnMetaFacts, comparisonWire, describeSet, fileWriter, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, isProjectInstallPath, lengthCheckLabel, lengthMeasure, measureCompare, measureExpression, moduleFileName, moduleSpecifier, needsNumericCanon, nestedArmNotes, nestedNodeColumns, nestedSchemaName, nestedTypeName, nonFiniteAccepted, nonFiniteRefused, parseCheck, parsesToADate, pascalCase, renderConstraintsModule, renderDuplicateFinder, resolveAffix, resolveBranding, resolveConfiguredImport, resolveConstraints, resolveNestedDepth, schemaName, selectColumns, tableConstraints, tableMetaFacts, typeName, updateColumns, validateAffix, wireLiteralFit, wireNumberLiteral };
package/dist/index.js CHANGED
@@ -13,6 +13,34 @@ function lengthMeasure(column, check) {
13
13
  if (column.tsType !== "string") return void 0;
14
14
  return check.unit === "bytes" ? "utf8Bytes" : "codePoints";
15
15
  }
16
+ function codePointCompare(variable, operator, bound) {
17
+ const units = `${variable}.length`;
18
+ const spread2 = `[...${variable}].length`;
19
+ switch (operator) {
20
+ case "<=":
21
+ case "<":
22
+ return `(${units} ${operator} ${bound} || ${spread2} ${operator} ${bound})`;
23
+ case ">=":
24
+ case ">":
25
+ return `(${units} ${operator} ${bound} && ${spread2} ${operator} ${bound})`;
26
+ case "===":
27
+ return `(${units} >= ${bound} && ${spread2} === ${bound})`;
28
+ case "!==":
29
+ return `(${units} < ${bound} || ${spread2} !== ${bound})`;
30
+ }
31
+ }
32
+ function measureCompare(measure, variable, operator, bound) {
33
+ const js = {
34
+ ">=": ">=",
35
+ ">": ">",
36
+ "<=": "<=",
37
+ "<": "<",
38
+ "=": "===",
39
+ "<>": "!=="
40
+ }[operator];
41
+ if (measure === "codePoints") return codePointCompare(variable, js, bound);
42
+ return `${measureExpression(measure, variable)} ${js} ${bound}`;
43
+ }
16
44
  function measureExpression(measure, variable) {
17
45
  switch (measure) {
18
46
  case "codePoints":
@@ -1844,6 +1872,7 @@ export {
1844
1872
  canonicalMembers,
1845
1873
  canonicalNumericText,
1846
1874
  classifyTableChecks,
1875
+ codePointCompare,
1847
1876
  columnMetaFacts,
1848
1877
  comparisonWire,
1849
1878
  describeSet,
@@ -1856,6 +1885,7 @@ export {
1856
1885
  isProjectInstallPath,
1857
1886
  lengthCheckLabel,
1858
1887
  lengthMeasure,
1888
+ measureCompare,
1859
1889
  measureExpression,
1860
1890
  moduleFileName,
1861
1891
  moduleSpecifier,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drzl/validation-core",
3
- "version": "3.22.2",
3
+ "version": "3.22.3",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -24,7 +24,7 @@
24
24
  ],
25
25
  "sideEffects": false,
26
26
  "dependencies": {
27
- "@drzl/analyzer": "^1.21.2"
27
+ "@drzl/analyzer": "^1.21.3"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "prettier": ">=3"