UNPKG

normul

Version:

Normul is a tiny TypeScript/JavaScript library for data normalization and transformation

171 lines 4.81 kB
export class Schema { modifiers = []; normalize(input) { const ctx = { path: [], issues: [], }; const data = this.invokeNormalize(this, input, ctx); return { data, issues: ctx.issues, }; } invokeNormalize(schema, input, ctx) { let currentModifierIndex = schema.modifiers.length - 1; const next = (input, ctx) => { if (currentModifierIndex >= 0) { const fn = schema.modifiers[currentModifierIndex--]; return fn(input, ctx, next); } return schema._normalize(input, ctx); }; return next(input, ctx); } makeIssue(options) { const { ctx, ...rest } = options; ctx.issues.push({ path: [...ctx.path], ...rest, }); } get optional() { const result = this.clone(); result.modifiers.push((input, ctx, next) => { if (input === undefined) { return undefined; } return next(input, ctx); }); return result; } get nullable() { const result = this.clone(); result.modifiers.push((input, ctx, next) => { if (input === null) { return null; } return next(input, ctx); }); return result; } default(value) { const result = this.clone(); result.modifiers.push((input, ctx, next) => { if (input === undefined || input === null) { this.makeIssue({ ctx, message: 'Using default value', level: 'info', }); return value; } return next(input, ctx); }); return result; } preprocess(fn) { const result = this.clone(); result.modifiers.push((input, ctx, next) => { let data = input; try { data = fn(input); } catch (error) { console.error(error); this.makeIssue({ ctx, message: `Caught exception in preprocess: ${error}`, level: 'error', }); } return next(data, ctx); }); return result; } transform(fn) { const result = this.clone(); result.modifiers.push((input, ctx, next) => { const data = next(input, ctx); try { return fn(data); } catch (error) { console.error(error); this.makeIssue({ ctx, message: `Caught exception in transform: ${error}`, level: 'error', }); return data; } }); return result; } type() { return new TypeSchema(this); } get any() { return new AnySchema(this); } get unknown() { return new UnknownSchema(this); } fallback(value) { const result = this.clone(); result.modifiers.push((input, ctx, next) => { const innerCtx = { issues: [], path: [], }; const data = next(input, innerCtx); ctx.issues.push(...innerCtx.issues); const shouldFallback = innerCtx.issues.some((issue) => { return (issue.level !== 'info' && issue.path.length === 0); }); if (shouldFallback) { this.makeIssue({ ctx, message: 'Using fallback value', level: 'info', }); return value; } return data; }); return result; } clone() { const Constructor = this.constructor; const result = new Constructor(...this.cloneArgs()); result.modifiers = [...this.modifiers]; this.cloneProps(result); return result; } cloneArgs() { return []; } // eslint-disable-next-line @typescript-eslint/no-unused-vars cloneProps(target) { // } } export class TypeSchema extends Schema { inner; constructor(inner) { super(); this.inner = inner; } _normalize(input, ctx) { return this.inner ? this.invokeNormalize(this.inner, input, ctx) : input; } } // eslint-disable-next-line @typescript-eslint/no-explicit-any export class AnySchema extends TypeSchema { } export class UnknownSchema extends TypeSchema { } //# sourceMappingURL=Schema.js.map