@webergency-utils/typechecker 0.1.9 → 0.2.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/dist/index.js CHANGED
@@ -1,3 +1,22 @@
1
+ const TRANSFORMER_MISSING = 'Typechecker transformer was not applied. Register { "transform": "@webergency-utils/typechecker/transformer" } in tsconfig plugins (requires ts-patch).';
2
+ /** Returns whether `input` already matches `T`. Does not coerce; `from` is ignored. */
3
+ export function is(_input, _options) {
4
+ throw new Error(TRANSFORMER_MISSING);
5
+ }
6
+ /** Validates and returns the (possibly coerced) value. Use `from` when conversion is needed. */
7
+ export function assert(_input, _options) {
8
+ throw new Error(TRANSFORMER_MISSING);
9
+ }
10
+ /** Asserts `input` already matches `T`. Does not coerce; `from` is ignored. */
11
+ export function assertGuard(_input, _options) {
12
+ throw new Error(TRANSFORMER_MISSING);
13
+ }
14
+ export function validate(_input, _options) {
15
+ throw new Error(TRANSFORMER_MISSING);
16
+ }
17
+ export function jsonSchema() {
18
+ throw new Error(TRANSFORMER_MISSING);
19
+ }
1
20
  export * from './runtime/validators.js';
2
21
  export * from './runtime/tags.js';
3
22
  export * from './runtime/casing.js';
@@ -0,0 +1,7 @@
1
+ import ts from 'typescript';
2
+ declare function init(modules: {
3
+ typescript: typeof ts;
4
+ }): {
5
+ create: (info: ts.server.PluginCreateInfo) => any;
6
+ };
7
+ export default init;
package/dist/plugin.js ADDED
@@ -0,0 +1,30 @@
1
+ import { collectStaticConstraintDiagnostics } from './engine/staticAsserts.js';
2
+ function init(modules) {
3
+ function create(info) {
4
+ const proxy = Object.create(null);
5
+ const ls = info.languageService;
6
+ for (const key of Object.keys(ls)) {
7
+ proxy[key] = ls[key];
8
+ }
9
+ proxy.getSemanticDiagnostics = (fileName) => {
10
+ const base = ls.getSemanticDiagnostics(fileName);
11
+ const program = ls.getProgram();
12
+ if (!program) {
13
+ return base;
14
+ }
15
+ const sourceFile = program.getSourceFile(fileName);
16
+ if (!sourceFile || sourceFile.isDeclarationFile) {
17
+ return base;
18
+ }
19
+ if (fileName.includes('node_modules')) {
20
+ return base;
21
+ }
22
+ const checker = program.getTypeChecker();
23
+ const extra = collectStaticConstraintDiagnostics(sourceFile, checker);
24
+ return [...base, ...extra];
25
+ };
26
+ return proxy;
27
+ }
28
+ return { create };
29
+ }
30
+ export default init;
@@ -12,7 +12,7 @@ type SnakeToPascal<S extends string> = Capitalize<SnakeToCamel<S>>;
12
12
  type SnakeToKebab<S extends string> = S extends `${infer L}_${infer R}` ? `${L}-${SnakeToKebab<R>}` : S;
13
13
  type SnakeToDot<S extends string> = S extends `${infer L}_${infer R}` ? `${L}.${SnakeToDot<R>}` : S;
14
14
  type SnakeToUpperSnake<S extends string> = Uppercase<S>;
15
- type ReplaceId<S extends string> = S extends `${infer L}Id` ? `${L}ID` : S extends `id` ? `ID` : S extends `Id` ? `ID` : S;
15
+ type ReplaceId<S extends string> = S extends `${infer L}Id` ? `${L}ID` : S extends 'id' ? 'ID' : S extends 'Id' ? 'ID' : S;
16
16
  type ToCamelCaseID<S extends string> = ReplaceId<SnakeToCamel<S>>;
17
17
  type ToPascalCaseID<S extends string> = ReplaceId<SnakeToPascal<S>>;
18
18
  type Leading<S extends string> = S extends `_${infer R}` ? `_${Leading<R>}` : S extends `-${infer R}` ? `-${Leading<R>}` : S extends `.${infer R}` ? `.${Leading<R>}` : S extends `$${infer R}` ? `$${Leading<R>}` : '';
@@ -20,9 +20,9 @@ type Trailing<S extends string> = S extends `${infer L}_` ? `${Trailing<L>}_` :
20
20
  type StripLeading<S extends string> = S extends `_${infer R}` ? StripLeading<R> : S extends `-${infer R}` ? StripLeading<R> : S extends `.${infer R}` ? StripLeading<R> : S extends `$${infer R}` ? StripLeading<R> : S;
21
21
  type StripTrailing<S extends string> = S extends `${infer L}_` ? StripTrailing<L> : S extends `${infer L}-` ? StripTrailing<L> : S extends `${infer L}.` ? StripTrailing<L> : S extends `${infer L}$` ? StripTrailing<L> : S;
22
22
  type FormatCoreCasing<S extends string, Casing extends CasingFormat> = Casing extends 'snake_case' ? Normalized<S> : Casing extends 'SNAKE_CASE' ? SnakeToUpperSnake<Normalized<S>> : Casing extends 'camelCase' ? SnakeToCamel<Normalized<S>> : Casing extends 'PascalCase' ? SnakeToPascal<Normalized<S>> : Casing extends 'kebab-case' ? SnakeToKebab<Normalized<S>> : Casing extends 'dot.case' ? SnakeToDot<Normalized<S>> : Casing extends 'camelCaseID' ? ToCamelCaseID<Normalized<S>> : Casing extends 'PascalCaseID' ? ToPascalCaseID<Normalized<S>> : S;
23
- export type FormatCasing<S extends string, Casing extends CasingFormat, Options extends ConvertCasingOptions = {}> = Options['preserveEnds'] extends false ? FormatCoreCasing<StripLeading<StripTrailing<S>>, Casing> : `${Leading<S>}${FormatCoreCasing<StripLeading<StripTrailing<S>>, Casing>}${Trailing<S>}`;
23
+ export type FormatCasing<S extends string, Casing extends CasingFormat, Options extends ConvertCasingOptions = Record<never, never>> = Options['preserveEnds'] extends false ? FormatCoreCasing<StripLeading<StripTrailing<S>>, Casing> : `${Leading<S>}${FormatCoreCasing<StripLeading<StripTrailing<S>>, Casing>}${Trailing<S>}`;
24
24
  type ExtractArray<T> = T extends any[] ? T : never;
25
- export type ConvertPropertyCasing<T, Casing extends CasingFormat, Options extends ConvertCasingOptions = {}> = T extends [infer F, ...infer R] ? [ConvertPropertyCasing<F, Casing, Options>, ...ExtractArray<ConvertPropertyCasing<R, Casing, Options>>] : T extends (infer E)[] ? ConvertPropertyCasing<E, Casing, Options>[] : T extends string | number | boolean | symbol | bigint | null | undefined ? T : T extends Date | RegExp | Function | Map<any, any> | Set<any> | Promise<any> ? T : T extends object ? {
25
+ export type ConvertPropertyCasing<T, Casing extends CasingFormat, Options extends ConvertCasingOptions = Record<never, never>> = T extends [infer F, ...infer R] ? [ConvertPropertyCasing<F, Casing, Options>, ...ExtractArray<ConvertPropertyCasing<R, Casing, Options>>] : T extends (infer E)[] ? ConvertPropertyCasing<E, Casing, Options>[] : T extends string | number | boolean | symbol | bigint | null | undefined ? T : T extends Date | RegExp | Function | Map<any, any> | Set<any> | Promise<any> ? T : T extends object ? {
26
26
  [K in keyof T as K extends string ? FormatCasing<K, Casing, Options> : K]: ConvertPropertyCasing<T[K], Casing, Options>;
27
27
  } : T;
28
28
  export declare function convertPropertyCasing<T, C extends CasingFormat>(obj: T, casing: C, options?: ConvertCasingOptions): ConvertPropertyCasing<T, C>;
@@ -2,7 +2,7 @@ function normalizeString(str) {
2
2
  if (/^[A-Z0-9_]+$/.test(str)) {
3
3
  str = str.toLowerCase();
4
4
  }
5
- str = str.replace(/[-\.]/g, '_');
5
+ str = str.replace(/[-.]/g, '_');
6
6
  str = str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
7
7
  return str.replace(/_+/g, '_').replace(/^_|_$/g, '');
8
8
  }
@@ -12,7 +12,7 @@ function formatCasing(str, casing, options = {}) {
12
12
  let trailing = '';
13
13
  let core = str;
14
14
  if (preserveEnds) {
15
- const match = str.match(/^([_\-\.\$]*)(.*?)([_\-\.\$]*)$/);
15
+ const match = str.match(/^([_\-.$]*)(.*?)([_\-.$]*)$/);
16
16
  if (match) {
17
17
  leading = match[1];
18
18
  core = match[2];
@@ -20,10 +20,10 @@ function formatCasing(str, casing, options = {}) {
20
20
  }
21
21
  }
22
22
  else {
23
- core = str.replace(/^([_\-\.\$]*)/, '').replace(/([_\-\.\$]*)$/, '');
23
+ core = str.replace(/^([_\-.$]*)/, '').replace(/([_\-.$]*)$/, '');
24
24
  }
25
25
  const normalized = normalizeString(core);
26
- let formatted = '';
26
+ let formatted;
27
27
  if (casing === 'snake_case') {
28
28
  formatted = normalized;
29
29
  }
@@ -1,5 +1,6 @@
1
1
  import type { Format } from './constraint.js';
2
2
  export type Email = Format<'email'>;
3
+ export type IdnEmail = Format<'idn-email'>;
3
4
  export type UUID = Format<'uuid'>;
4
5
  export type URL = Format<'url'>;
5
6
  export type IPv4 = Format<'ipv4'>;
@@ -10,6 +11,12 @@ export type Byte = Format<'byte'>;
10
11
  export type Password = Format<'password'>;
11
12
  export type Regex = Format<'regex'>;
12
13
  export type Hostname = Format<'hostname'>;
14
+ export type IdnHostname = Format<'idn-hostname'>;
15
+ export type URI = Format<'uri'>;
16
+ export type UriReference = Format<'uri-reference'>;
17
+ export type IRI = Format<'iri'>;
18
+ export type IriReference = Format<'iri-reference'>;
19
+ export type UriTemplate = Format<'uri-template'>;
13
20
  export type Time = Format<'time'>;
14
21
  export type Duration = Format<'duration'>;
15
22
  export type ObjectId = Format<'objectId'>;
@@ -1,3 +1,3 @@
1
- export type Default<V extends string | number | boolean | null> = {
1
+ export type Default<V = any> = {
2
2
  readonly __default?: V;
3
3
  };
@@ -47,7 +47,7 @@ type IsAny<T> = 0 extends 1 & T ? true : false;
47
47
  * Recursively resolves object properties, removing the optional `?` modifier
48
48
  * from any properties that have a `tag.Default` applied.
49
49
  */
50
- export type ResolveDefaults<T> = T extends Date | symbol | string | number | boolean | bigint | null | undefined | Function ? T : T extends Array<infer U> ? Array<ResolveDefaults<U>> : T extends object ? {
50
+ export type ResolveDefaults<T> = T extends Date | RegExp | Promise<any> | Map<any, any> | Set<any> | ArrayBuffer | SharedArrayBuffer | DataView | Buffer | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array | symbol | string | number | boolean | bigint | null | undefined | Function ? T : T extends Array<infer U> ? Array<ResolveDefaults<U>> : T extends object ? {
51
51
  [K in keyof T as IsAny<T[K]> extends true ? never : '__default' extends keyof NonNullable<T[K]> ? K : never]-?: ResolveDefaults<Exclude<T[K], undefined>>;
52
52
  } & {
53
53
  [K in keyof T as IsAny<T[K]> extends true ? K : '__default' extends keyof NonNullable<T[K]> ? never : K]: ResolveDefaults<T[K]>;
@@ -3,27 +3,48 @@ export interface IValidationError {
3
3
  path: string;
4
4
  value: any;
5
5
  error: string;
6
+ /** Nested failures (e.g. per-arm errors for a failed union). */
7
+ issues?: IValidationError[];
6
8
  }
9
+ /** Internal expected-type labels for custom `from` callbacks. Not exported from the package. */
10
+ type BaseType = 'string' | 'number' | 'boolean' | 'bigint' | 'function' | 'symbol' | 'never' | 'Date' | 'RegExp' | 'Set' | 'Map' | 'Array' | 'Object' | 'instance' | 'null' | 'undefined' | 'tuple' | 'literal';
11
+ type FromOption = 'json' | 'query' | ((key: string, value: any, type: BaseType) => any);
7
12
  export interface ValidationContext {
8
13
  success: boolean;
9
14
  errors: IValidationError[];
10
15
  mode: ValidationMode;
11
- tryConvert?: boolean;
16
+ from?: FromOption;
12
17
  wrapArrays?: boolean;
18
+ mutate?: boolean;
13
19
  root?: any;
14
20
  }
15
21
  export interface ValidationOptions {
16
22
  mode?: ValidationMode;
17
- tryConvert?: boolean;
23
+ from?: FromOption;
18
24
  wrapArrays?: boolean;
25
+ /** When true, write validated/coerced values onto the input. Default false: always return new containers. */
26
+ mutate?: boolean;
19
27
  schema?: any;
20
28
  errorFactory?: (errors: IValidationError[]) => Error;
21
29
  }
30
+ /** Query-style number coercion — shared by `from: 'query'` and `transform.ToNumber`. */
31
+ export declare function coerceQueryNumber(v: any): any;
32
+ /** Query-style boolean coercion — shared by `from: 'query'` and `transform.ToBoolean`. */
33
+ export declare function coerceQueryBoolean(v: any): any;
34
+ /** JSON-wire Date revival (ISO / date-parseable strings only). */
35
+ export declare function coerceJsonDate(v: any): any;
36
+ /** Query-style Date coercion — shared by `from: 'query'` and `transform.ToDate`. */
37
+ export declare function coerceQueryDate(v: any): any;
22
38
  export declare const validators: {
39
+ coerceQueryNumber: typeof coerceQueryNumber;
40
+ coerceQueryBoolean: typeof coerceQueryBoolean;
41
+ coerceQueryDate: typeof coerceQueryDate;
42
+ coerceJsonDate: typeof coerceJsonDate;
23
43
  string: (v: any, path: string, ctx: ValidationContext) => any;
24
44
  number: (v: any, path: string, ctx: ValidationContext) => any;
25
45
  bigint: (v: any, path: string, ctx: ValidationContext) => any;
26
46
  boolean: (v: any, path: string, ctx: ValidationContext) => any;
47
+ function: (v: any, path: string, ctx: ValidationContext) => any;
27
48
  date: (v: any, path: string, ctx: ValidationContext) => any;
28
49
  regexp: (v: any, path: string, ctx: ValidationContext) => any;
29
50
  null: (v: any, path: string, ctx: ValidationContext) => null;
@@ -31,7 +52,10 @@ export declare const validators: {
31
52
  literal: (v: any, path: string, ctx: ValidationContext, expected: any) => any;
32
53
  array: (v: any, path: string, ctx: ValidationContext, childValidator: Function) => any;
33
54
  props: (v: any, data: any, path: string, ctx: ValidationContext, props: [string, boolean, Function][]) => void;
34
- object: (v: any, path: string, ctx: ValidationContext, allowedKeys?: string[], expected?: string) => boolean;
55
+ objectShell: (v: any, ctx: ValidationContext) => any;
56
+ stripExtras: (data: any, ctx: ValidationContext, allowedKeys?: string[]) => any;
57
+ additionalProps: (v: any, data: any, path: string, ctx: ValidationContext, knownKeys: string[], childValidator: Function) => void;
58
+ object: (v: any, path: string, ctx: ValidationContext, allowedKeys?: string[], expected?: string) => any;
35
59
  templateLiteral: (v: any, path: string, ctx: ValidationContext, regex: RegExp, expected: string) => any;
36
60
  minLength: (v: string, path: string, ctx: ValidationContext, min: number, message?: string) => string;
37
61
  maxLength: (v: string, path: string, ctx: ValidationContext, max: number, message?: string) => string;
@@ -41,7 +65,7 @@ export declare const validators: {
41
65
  exclusiveMaximum: (v: number | bigint, path: string, ctx: ValidationContext, max: number | bigint, message?: string) => number | bigint;
42
66
  multipleOf: (v: number | bigint, path: string, ctx: ValidationContext, n: number | bigint, message?: string) => number | bigint;
43
67
  pattern: (v: string, path: string, ctx: ValidationContext, regex: RegExp, expected: string, message?: string) => string;
44
- format: (v: string, path: string, ctx: ValidationContext, format: string, message?: string) => string;
68
+ format: (v: string, path: string, ctx: ValidationContext, format: string, message?: string) => any;
45
69
  minItems: (v: any[], path: string, ctx: ValidationContext, min: number, message?: string) => any[];
46
70
  maxItems: (v: any[], path: string, ctx: ValidationContext, max: number, message?: string) => any[];
47
71
  uniqueItems: (v: any[], path: string, ctx: ValidationContext, message?: string) => any[];
@@ -49,6 +73,9 @@ export declare const validators: {
49
73
  union: (v: any, path: string, ctx: ValidationContext, checks: Function[], expected?: string) => any;
50
74
  tuple: (v: any, path: string, ctx: ValidationContext, checks: Function[]) => any;
51
75
  any: (v: any) => any;
76
+ never: (v: any, path: string, ctx: ValidationContext) => any;
77
+ symbol: (v: any, path: string, ctx: ValidationContext) => any;
78
+ instanceOf: (v: any, path: string, ctx: ValidationContext, typeName: string) => any;
52
79
  requires: (v: any, path: string, ctx: ValidationContext, reqs: string[], message?: string) => any;
53
80
  record: (v: any, path: string, ctx: ValidationContext, childValidator: Function) => any;
54
81
  set: (v: any, path: string, ctx: ValidationContext, childValidator: Function, message?: string) => any;
@@ -65,6 +92,7 @@ export declare class MetadataStoreClass {
65
92
  getOrCompileSchema(schema: any): Function;
66
93
  is(validator: Function, value: any, options?: ValidationMode | ValidationOptions): boolean;
67
94
  assert(validator: Function, value: any, options?: ValidationMode | ValidationOptions): any;
95
+ assertGuard(validator: Function, value: any, options?: ValidationMode | ValidationOptions): void;
68
96
  validate(validator: Function, value: any, options?: ValidationMode | ValidationOptions): {
69
97
  success: boolean;
70
98
  errors: IValidationError[];
@@ -77,13 +105,9 @@ export declare function groupErrorsByPath(errors: IValidationError[]): Record<st
77
105
  }>;
78
106
  export declare const MetadataStore: MetadataStoreClass;
79
107
  export declare function compileSchema(schema: any): (v: any, path: string, ctx: any) => any;
80
- export declare function toZodIssues(errors: IValidationError[]): {
81
- code: string;
82
- path: (string | number)[];
83
- message: string;
84
- received: any;
85
- }[];
108
+ export declare function toZodIssues(errors: IValidationError[]): any[];
86
109
  export declare class ZodLikeError extends Error {
87
110
  issues: any[];
88
111
  constructor(errors: IValidationError[]);
89
112
  }
113
+ export {};