dagatsoin
dagatsoin

Reputation: 2656

how to use mongo schema validation with typescript in meteor?

Is there a package to use schema validation in Meteor 1.3 when using Typescript. The recommended package from the Meteor guide (aldeed:simple-schema) does not seem to have a definition file.

So what to use instead, or maybe Typescript has a built-in way to do this?

Upvotes: 4

Views: 1598

Answers (1)

Quentin Kramer
Quentin Kramer

Reputation: 63

The best package to use for Meteor 1.3 and up with Typescript is aldeed:node-simple-schema.

From the docs:

The History of SimpleSchema

SimpleSchema was first released as a Meteor package in mid-2013. Version 1.0 was released in September 2014. In mid-2016, version 2.0 was released as an NPM package, which can be used in Meteor, NodeJS, or static browser apps.

Installation

npm install simpl-schema There are other NPM packages named simpleschema and simple-schema. Make sure you install the right package. There is no "e" on "simpl".

So the correct import in Typescript looks like this:

import SimpleSchema from 'simpl-schema';

But your question is specifically about typings. The place to start for Meteor typings is the Meteor typings library at https://github.com/meteor-typescript/meteor-typescript-libs/tree/master/definitions.
Within it, you'll find definitions for collection2 and simple-schema, but it's the old simple-schema. They do give you a good starting point, and you'll want to come back and pick up the collection2 ones in a bit. Ultimately, after about a week of searching/etc. I wrote my own set, based on the original on the Meteor Git. Hopefully they are helpful to some future searcher, even if they are a bit late for you.

declare module "simpl-schema" {

export class ValidationContext {
    constructor(ss: any);
    addValidationErrors(errors: any): void;
    clean(...args: any[]): any;
    getErrorForKey(key: any, ...args: any[]): any;
    isValid(): any;
    keyErrorMessage(key: any, ...args: any[]): any;
    keyIsInvalid(key: any, ...args: any[]): any;
    reset(): void;
    setValidationErrors(errors: any): void;
    validate(obj: any, ...args: any[]): any;
    validationErrors(): any;
}

interface SchemaDefinition {
    type: any;
    label?: string | Function;
    optional?: boolean | Function;
    min?: number | boolean | Date | Function;
    max?: number | boolean | Date | Function;
    minCount?: number | Function;
    maxCount?: number | Function;
    allowedValues?: any[] | Function;
    decimal?: boolean;
    exclusiveMax?: boolean;
    exclusiveMin?: boolean;
    regEx?: RegExp | RegExp[];
    custom?: Function;
    blackbox?: boolean;
    autoValue?: Function;
    defaultValue?: any;
    trim?: boolean;
}

interface CleanOption {
  filter?: boolean;
  autoConvert?: boolean;
  removeEmptyStrings?: boolean;
  trimStrings?: boolean;
  getAutoValues?: boolean;
  isModifier?: boolean;
  extendAutoValueContext?: boolean;
}

interface SimpleSchemaStatic {
  new(schema: {[key: string]: SchemaDefinition} | any[]): SimpleSchemaStatic;
  debug: boolean;
  namedContext(name?: string): SimpleSchemaValidationContextStatic;
  addValidator(validator: Function): any;
  pick(...fields: string[]): SimpleSchemaStatic;
  omit(...fields: string[]): SimpleSchemaStatic;
  clean(doc: any, options?: CleanOption): any;
  schema(key?: string): SchemaDefinition | SchemaDefinition[];
  getDefinition(key: string, propList?: any, functionContext?: any): any;
  keyIsInBlackBox(key: string): boolean;
  labels(labels: {[key: string]: string}): void;
  label(key: any): any;
  Integer: RegExp;
  messages(messages: any): void;
  messageForError(type: any, key: any, def: any, value: any): string;
  allowsKey(key: any): string;
  newContext(): SimpleSchemaValidationContextStatic;
  objectKeys(keyPrefix: any): any[];
  validate(obj: any, options?: ValidationOption): void;
  validator(options: ValidationOption): Function;
  RegEx: {
      Email: RegExp;
      EmailWithTLD: RegExp;
      Domain: RegExp;
      WeakDomain: RegExp;
      IP: RegExp;
      IPv4: RegExp;
      IPv6: RegExp;
      Url: RegExp;
      Id: RegExp;
      ZipCode: RegExp;
      Phone: RegExp;
  };
}

interface ValidationOption {
    modifier?: boolean;
    upsert?: boolean;
    clean?: boolean;
    filter?: boolean;
    upsertextendedCustomContext?: boolean;
}

interface SimpleSchemaValidationContextStatic {
    validate(obj: any, options?: ValidationOption): boolean;
    validateOne(doc: any, keyName: string, options?: ValidationOption): boolean;
    resetValidation(): void;
    isValid(): boolean;
    invalidKeys(): { name: string; type: string; value?: any; }[];
    addInvalidKeys(errors: { name: string, type: string; }[]): void;
    keyIsInvalid(name: any): boolean;
    keyErrorMessage(name: any): string;
    getErrorObject(): any;
}

interface MongoObjectStatic {
    forEachNode(func: Function, options?: {endPointsOnly: boolean;}): void;
    getValueForPosition(position: string): any;
    setValueForPosition(position: string, value: any): void;
    removeValueForPosition(position: string): void;
    getKeyForPosition(position: string): any;
    getGenericKeyForPosition(position: string): any;
    getInfoForKey(key: string): any;
    getPositionForKey(key: string): string;
    getPositionsForGenericKey(key: string): string[];
    getValueForKey(key: string): any;
    addKey(key: string, val: any, op: string): any;
    removeGenericKeys(keys: string[]): void;
    removeGenericKey(key: string): void;
    removeKey(key: string): void;
    removeKeys(keys: string[]): void;
    filterGenericKeys(test: Function): void;
    setValueForKey(key: string, val: any): void;
    setValueForGenericKey(key: string, val: any): void;
    getObject(): any;
    getFlatObject(options?: {keepArrays?: boolean}): any;
    affectsKey(key: string): any;
    affectsGenericKey(key: string): any;
    affectsGenericKeyImplicit(key: string): any;
}

export const SimpleSchema: SimpleSchemaStatic;
export const SimpleSchemaValidationContext: SimpleSchemaValidationContextStatic;
export const MongoObject: MongoObjectStatic;

export interface SimpleSchema {
  debug: boolean;
  addValidator(validator: Function): any;
  extendOptions(options: {[key: string]: any}): void;
  messages(messages: any): void;
  RegEx: {
      Email: RegExp;
      Domain: RegExp;
      WeakDomain: RegExp;
      IP: RegExp;
      IPv4: RegExp;
      IPv6: RegExp;
      Url: RegExp;
      Id: RegExp;
      ZipCode: RegExp;
      Phone: RegExp;
  };
}

export interface MongoObject {
  expandKey(val: any, key: string, obj: any): void;
}

export default SimpleSchema;
}

This is based off the most recent versions of each as of 4/23/2017.

For bonus points, here's the set for validated-method, which you'll be looking for next:

declare module "meteor/mdg:validated-method" {
    declare class ValidatedMethod<T> extends MeteorValidatedMethod.ValidatedMethod<T> { }

    declare module MeteorValidatedMethod {
        export class ValidatedMethod<T> {
            constructor(options: ValidatedMethodOptions<T>);
            call(options?: T, cb?: (err, res)=> void): void;
        }

        interface ValidatedMethodOptions<T> {
            name: string;
            mixins?: Function[];
            validate: any;
            applyOptions: any;
            run(opts: T);
        }
    }
}

For the searcher who's embarking into schemas and validation in the Meteor world, here are a few more modules that will help round out your validation package:

aldeed:collection2-core       2.0.0  Core package for aldeed:collection2
aldeed:schema-deny            2.0.0  Deny inserting or updating certain properties through schema options
aldeed:schema-index           2.0.0  Control some MongoDB indexing with schema options
mdg:validated-method          1.1.0  A simple wrapper for Meteor.methods
mdg:validation-error          0.5.1  A standard validation error to be used by form/method/validation packages

Upvotes: 5

Related Questions