@drzl/validation-core 3.11.0 → 3.13.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/dist/index.cjs CHANGED
@@ -84473,6 +84473,8 @@ module.exports = __toCommonJS(index_exports2);
84473
84473
  // src/checks.ts
84474
84474
  var COMPARISON = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*(>=|<=|<>|!=|>|<|=)\s*(.+?)\s*$/;
84475
84475
  var IN_LIST = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s+IN\s*\((.+)\)\s*$/i;
84476
+ var CARDINALITY_OF = /^\s*(?:cardinality\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)|array_length\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*,\s*1\s*\))\s*(>=|<=|<>|!=|>|<|=)\s*(\d+)\s*$/i;
84477
+ var LENGTH_OF = /^\s*(?:length|char_length)\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)\s*(>=|<=|<>|!=|>|<|=)\s*(\d+)\s*$/i;
84476
84478
  function splitTopLevelAnd(expr) {
84477
84479
  const parts = [];
84478
84480
  let depth = 0;
@@ -84593,6 +84595,8 @@ function parseCheck(expression, name) {
84593
84595
  const checks = [];
84594
84596
  const sets = [];
84595
84597
  const rows = [];
84598
+ const lengths = [];
84599
+ const cardinalities = [];
84596
84600
  for (const part of parts) {
84597
84601
  const parsed = parseCheck(part, name);
84598
84602
  if (!parsed.ok)
@@ -84600,12 +84604,41 @@ function parseCheck(expression, name) {
84600
84604
  checks.push(...parsed.checks);
84601
84605
  if (parsed.sets) sets.push(...parsed.sets);
84602
84606
  if (parsed.rows) rows.push(...parsed.rows);
84607
+ if (parsed.lengths) lengths.push(...parsed.lengths);
84608
+ if (parsed.cardinalities) cardinalities.push(...parsed.cardinalities);
84603
84609
  }
84604
84610
  return {
84605
84611
  ok: true,
84606
84612
  checks,
84607
84613
  ...sets.length ? { sets } : {},
84608
- ...rows.length ? { rows } : {}
84614
+ ...rows.length ? { rows } : {},
84615
+ ...lengths.length ? { lengths } : {},
84616
+ ...cardinalities.length ? { cardinalities } : {}
84617
+ };
84618
+ }
84619
+ const lengthOf = expr.match(LENGTH_OF);
84620
+ if (lengthOf) {
84621
+ const op4 = lengthOf[2] === "!=" ? "<>" : lengthOf[2];
84622
+ return {
84623
+ ok: true,
84624
+ checks: [],
84625
+ lengths: [{ column: lengthOf[1], operator: op4, value: lengthOf[3], name }]
84626
+ };
84627
+ }
84628
+ const cardinalityOf = expr.match(CARDINALITY_OF);
84629
+ if (cardinalityOf) {
84630
+ const op4 = cardinalityOf[3] === "!=" ? "<>" : cardinalityOf[3];
84631
+ return {
84632
+ ok: true,
84633
+ checks: [],
84634
+ cardinalities: [
84635
+ {
84636
+ column: cardinalityOf[1] ?? cardinalityOf[2],
84637
+ operator: op4,
84638
+ value: cardinalityOf[4],
84639
+ ...name ? { name } : {}
84640
+ }
84641
+ ]
84609
84642
  };
84610
84643
  }
84611
84644
  const inList = expr.match(IN_LIST);
package/dist/index.d.cts CHANGED
@@ -230,12 +230,40 @@ interface RowCheck {
230
230
  operator: ColumnCheck['operator'];
231
231
  name?: string;
232
232
  }
233
+ /**
234
+ * A constraint on a column's *character* count, from `CHECK (length(name) > 3)`.
235
+ *
236
+ * Kept apart from `ColumnCheck` because it is not a comparison of the value: it compares a count
237
+ * derived from it, and the count Postgres takes is code points rather than UTF-16 units. See
238
+ * `CODEPOINT_LENGTH` for why that distinction is load bearing.
239
+ */
240
+ interface LengthCheck {
241
+ column: string;
242
+ operator: ColumnCheck['operator'];
243
+ /** Decimal, as text, matching how the other bounds are carried. */
244
+ value: string;
245
+ name?: string;
246
+ }
247
+ /**
248
+ * A constraint on an array column's element count, from `CHECK (cardinality(tags) > 0)`.
249
+ *
250
+ * The array analogue of `LengthCheck`, and free of the question that one carries: an element
251
+ * count is the same number in SQL and in JavaScript, with no encoding involved.
252
+ */
253
+ interface CardinalityCheck {
254
+ column: string;
255
+ operator: ColumnCheck['operator'];
256
+ value: string;
257
+ name?: string;
258
+ }
233
259
  /** A check that was understood, or the reason it was not. */
234
260
  type ParsedCheck = {
235
261
  ok: true;
236
262
  checks: ColumnCheck[];
237
263
  sets?: ColumnSet[];
238
264
  rows?: RowCheck[];
265
+ lengths?: LengthCheck[];
266
+ cardinalities?: CardinalityCheck[];
239
267
  } | {
240
268
  ok: false;
241
269
  reason: string;
@@ -433,4 +461,4 @@ declare function updateColumns(table: Table): Column[];
433
461
  declare function selectColumns(table: Table): Column[];
434
462
  declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
435
463
 
436
- export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COLUMN_FORMATS, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, parseCheck, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
464
+ export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COLUMN_FORMATS, type CardinalityCheck, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, parseCheck, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
package/dist/index.d.ts CHANGED
@@ -230,12 +230,40 @@ interface RowCheck {
230
230
  operator: ColumnCheck['operator'];
231
231
  name?: string;
232
232
  }
233
+ /**
234
+ * A constraint on a column's *character* count, from `CHECK (length(name) > 3)`.
235
+ *
236
+ * Kept apart from `ColumnCheck` because it is not a comparison of the value: it compares a count
237
+ * derived from it, and the count Postgres takes is code points rather than UTF-16 units. See
238
+ * `CODEPOINT_LENGTH` for why that distinction is load bearing.
239
+ */
240
+ interface LengthCheck {
241
+ column: string;
242
+ operator: ColumnCheck['operator'];
243
+ /** Decimal, as text, matching how the other bounds are carried. */
244
+ value: string;
245
+ name?: string;
246
+ }
247
+ /**
248
+ * A constraint on an array column's element count, from `CHECK (cardinality(tags) > 0)`.
249
+ *
250
+ * The array analogue of `LengthCheck`, and free of the question that one carries: an element
251
+ * count is the same number in SQL and in JavaScript, with no encoding involved.
252
+ */
253
+ interface CardinalityCheck {
254
+ column: string;
255
+ operator: ColumnCheck['operator'];
256
+ value: string;
257
+ name?: string;
258
+ }
233
259
  /** A check that was understood, or the reason it was not. */
234
260
  type ParsedCheck = {
235
261
  ok: true;
236
262
  checks: ColumnCheck[];
237
263
  sets?: ColumnSet[];
238
264
  rows?: RowCheck[];
265
+ lengths?: LengthCheck[];
266
+ cardinalities?: CardinalityCheck[];
239
267
  } | {
240
268
  ok: false;
241
269
  reason: string;
@@ -433,4 +461,4 @@ declare function updateColumns(table: Table): Column[];
433
461
  declare function selectColumns(table: Table): Column[];
434
462
  declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
435
463
 
436
- export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COLUMN_FORMATS, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, parseCheck, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
464
+ export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COLUMN_FORMATS, type CardinalityCheck, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, parseCheck, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
package/dist/index.js CHANGED
@@ -3,6 +3,8 @@ import "./chunk-ZZGILH5A.js";
3
3
  // src/checks.ts
4
4
  var COMPARISON = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*(>=|<=|<>|!=|>|<|=)\s*(.+?)\s*$/;
5
5
  var IN_LIST = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s+IN\s*\((.+)\)\s*$/i;
6
+ var CARDINALITY_OF = /^\s*(?:cardinality\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)|array_length\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*,\s*1\s*\))\s*(>=|<=|<>|!=|>|<|=)\s*(\d+)\s*$/i;
7
+ var LENGTH_OF = /^\s*(?:length|char_length)\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)\s*(>=|<=|<>|!=|>|<|=)\s*(\d+)\s*$/i;
6
8
  function splitTopLevelAnd(expr) {
7
9
  const parts = [];
8
10
  let depth = 0;
@@ -123,6 +125,8 @@ function parseCheck(expression, name) {
123
125
  const checks = [];
124
126
  const sets = [];
125
127
  const rows = [];
128
+ const lengths = [];
129
+ const cardinalities = [];
126
130
  for (const part of parts) {
127
131
  const parsed = parseCheck(part, name);
128
132
  if (!parsed.ok)
@@ -130,12 +134,41 @@ function parseCheck(expression, name) {
130
134
  checks.push(...parsed.checks);
131
135
  if (parsed.sets) sets.push(...parsed.sets);
132
136
  if (parsed.rows) rows.push(...parsed.rows);
137
+ if (parsed.lengths) lengths.push(...parsed.lengths);
138
+ if (parsed.cardinalities) cardinalities.push(...parsed.cardinalities);
133
139
  }
134
140
  return {
135
141
  ok: true,
136
142
  checks,
137
143
  ...sets.length ? { sets } : {},
138
- ...rows.length ? { rows } : {}
144
+ ...rows.length ? { rows } : {},
145
+ ...lengths.length ? { lengths } : {},
146
+ ...cardinalities.length ? { cardinalities } : {}
147
+ };
148
+ }
149
+ const lengthOf = expr.match(LENGTH_OF);
150
+ if (lengthOf) {
151
+ const op2 = lengthOf[2] === "!=" ? "<>" : lengthOf[2];
152
+ return {
153
+ ok: true,
154
+ checks: [],
155
+ lengths: [{ column: lengthOf[1], operator: op2, value: lengthOf[3], name }]
156
+ };
157
+ }
158
+ const cardinalityOf = expr.match(CARDINALITY_OF);
159
+ if (cardinalityOf) {
160
+ const op2 = cardinalityOf[3] === "!=" ? "<>" : cardinalityOf[3];
161
+ return {
162
+ ok: true,
163
+ checks: [],
164
+ cardinalities: [
165
+ {
166
+ column: cardinalityOf[1] ?? cardinalityOf[2],
167
+ operator: op2,
168
+ value: cardinalityOf[4],
169
+ ...name ? { name } : {}
170
+ }
171
+ ]
139
172
  };
140
173
  }
141
174
  const inList = expr.match(IN_LIST);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drzl/validation-core",
3
- "version": "3.11.0",
3
+ "version": "3.13.0",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",