diff --git a/sails.io.js/index.d.ts b/sails.io.js/index.d.ts
new file mode 100644
index 0000000000..362b4cb66f
--- /dev/null
+++ b/sails.io.js/index.d.ts
@@ -0,0 +1,100 @@
+// Type definitions for sails.io.js 1.0.1
+// Project: http://sailsjs.org/documentation/reference/web-sockets/socket-client
+// Definitions by: Arvitaly
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+///
+
+declare namespace SailsIOJS {
+ export interface SDKInfo {
+ version?: string;
+ language?: string;
+ platform?: "browser" | "node";
+ versionString?: string;
+ }
+ export interface ClientSails {
+ url?: string;
+ autoConnect?: boolean;
+ headers?: { [index: string]: string };
+ transports?: Array<"websocket" | "polling">;
+ rejectUnauthorized?: boolean;
+ reconnection?: boolean;
+ reconnectionAttempts?: number;
+ reconnectionDelay?: number;
+ reconnectionDelayMax?: number;
+ useCORSRouteToGetCookie?: boolean;
+ query?: string;
+ path?: string;
+ // All logs are disabled when `io.sails.environment = 'production'`
+ environment?: "production" | string;
+ connect(url?: string, config?: ConnectConfig): Socket;
+ initialConnectionHeaders?: InitialConnectionHeaders;
+ strict?: boolean;
+ sdk?: SDKInfo;
+ }
+ export interface ConnectConfig {
+ initialConnectionHeaders?: InitialConnectionHeaders
+ }
+ export interface InitialConnectionHeaders {
+ nosession?: boolean;
+ }
+ export interface Client {
+ socket: Socket;
+ sails: ClientSails;
+ }
+ export interface Headers { [index: string]: string }
+ export interface RequestOptions {
+ url: string;
+ method?: string;
+ headers?: Headers;
+ params?: any;
+ data?: any;
+ }
+ export interface JWR {
+ headers: Headers;
+ statusCode: number;
+ body: any;
+ error?: Error;
+ toString: () => string;
+ toPOJO: () => {
+ body: any;
+ headers: Headers;
+ statusCode: number;
+ }
+ pipe: () => Error;
+ }
+ export type RequestCallback = {
+ (body: any, jwr: JWR): any;
+ }
+ export type Data = Object;
+ export interface Socket {
+ get(url: string, data?: Data): void;
+ get(url: string, cb?: RequestCallback): void;
+ get(url: string, data: Data, cb: RequestCallback): void;
+ post(url: string, data?: Data): void;
+ post(url: string, cb?: RequestCallback): void;
+ post(url: string, data: Data, cb: RequestCallback): void;
+ put(url: string, data?: Data): void;
+ put(url: string, cb?: RequestCallback): void;
+ put(url: string, data: Data, cb: RequestCallback): void;
+ delete(url: string, data?: Data): void;
+ delete(url: string, cb?: RequestCallback): void;
+ delete(url: string, data: Data, cb: RequestCallback): void;
+ request(options: RequestOptions, cb?: RequestCallback): void;
+ on(event: string, cb: (...args: Array) => any): Socket;
+ on(event: "connect", cb: () => any): Socket;
+ on(event: "disconnect", cb: () => any): Socket;
+ on(event: "reconnecting", cb: (numAttempts: number) => any): Socket;
+ on(event: "reconnect", cb: (transport: string, numAttempts: number) => any): Socket;
+ on(event: "error", cb: (err: any) => any): Socket;
+ off(event: string, cb: () => any): Socket
+ removeAllListeners(): Socket;
+ isConnecting(): boolean;
+ isConnected(): boolean;
+ reconnect(): Socket;
+ mightBeAboutToAutoConnect(): boolean;
+ replay(): Socket;
+ }
+}
+declare function SailsIOJS(client: SocketIOClientStatic): SailsIOJS.Client;
+export = SailsIOJS;
\ No newline at end of file
diff --git a/sails.io.js/sails.io.js-tests.ts b/sails.io.js/sails.io.js-tests.ts
new file mode 100644
index 0000000000..890d0d6b2f
--- /dev/null
+++ b/sails.io.js/sails.io.js-tests.ts
@@ -0,0 +1,88 @@
+import SocketIO = require('socket.io-client');
+import SailsIOJS = require('.');
+const io = SailsIOJS(SocketIO);
+io.sails.autoConnect = true;
+io.sails.connect();
+io.sails.connect("url");
+io.sails.connect("url", {});
+io.sails.connect("url", {
+ initialConnectionHeaders: {
+ nosession: true
+ }
+});
+io.sails.environment = "production";
+io.sails.headers = { "test": "1" };
+io.sails.initialConnectionHeaders = { nosession: false };
+io.sails.path = "path";
+io.sails.query = "query";
+io.sails.reconnection = true;
+io.sails.reconnectionAttempts = 5;
+io.sails.reconnectionDelay = 1;
+io.sails.reconnectionDelayMax = 5;
+io.sails.rejectUnauthorized = true;
+io.sails.sdk = {
+ language: "lang",
+ platform: "node",
+ version: "1.0",
+ versionString: "1.0"
+}
+io.sails.strict = true;
+io.sails.transports = ["websocket", "polling"];
+io.sails.url = "url1";
+io.sails.useCORSRouteToGetCookie = true;
+io.socket.get("p");
+io.socket.get("p", {});
+io.socket.get("p", "test", (data: Date, jwr: any) => {
+ data.getDate();
+ const a: SailsIOJS.JWR = jwr;
+});
+io.socket.post("p");
+io.socket.post("p", { val: 1 });
+io.socket.put("p", "test", (data: number, jwr: any) => {
+ data.toFixed();
+ const a: SailsIOJS.JWR = jwr;
+});
+io.socket.put("p");
+io.socket.put("p", {});
+io.socket.post("p", "test", (data, jwr) => {
+ const a: SailsIOJS.JWR = jwr;
+});
+io.socket.delete("p");
+io.socket.delete("p", {});
+io.socket.delete("p", "test", (data, jwr) => {
+ const a: SailsIOJS.JWR = jwr;
+});
+io.socket.request({ url: "url" });
+io.socket.request({ url: "url" }, (data: number, jwr: any) => {
+ data.toExponential();
+ jwr.body.toExponential();
+ jwr.error.message;
+ jwr.pipe.apply(this);
+ jwr.statusCode.toFixed();
+ const podo = jwr.toPOJO();
+ podo.body.toExponential();
+ podo.headers["test"] = "15";
+ podo.statusCode = 200;
+ jwr.toString().charAt(0);
+})
+io.socket.isConnected() === true;
+io.socket.isConnecting() === true;
+io.socket.mightBeAboutToAutoConnect() === false;
+io.socket.on("connect", () => { })
+ .on("disconnect", () => {
+
+ })
+ .on("reconnecting", (num) => {
+ num = 15;
+ })
+ .on("reconnect", (transport, num) => {
+ transport.toLowerCase();
+ num = 16;
+ })
+ .on("error", (err) => { })
+ .on("any", (a, b, c) => {
+
+ })
+ .removeAllListeners()
+ .off("error", () => { })
+ .replay();
\ No newline at end of file
diff --git a/sails.io.js/tsconfig.json b/sails.io.js/tsconfig.json
new file mode 100644
index 0000000000..2e73761b08
--- /dev/null
+++ b/sails.io.js/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es6",
+ "noImplicitAny": true,
+ "strictNullChecks": true,
+ "baseUrl": "../",
+ "typeRoots": [
+ "../"
+ ],
+ "types": [],
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.d.ts",
+ "sails.io.js-tests.ts"
+ ]
+}
\ No newline at end of file
diff --git a/waterline/index.d.ts b/waterline/index.d.ts
new file mode 100644
index 0000000000..55bfd1673c
--- /dev/null
+++ b/waterline/index.d.ts
@@ -0,0 +1,239 @@
+import BluebirdPromise = require("bluebird");
+declare namespace Waterline {
+ type Adapter = Object;
+ type Connection = {
+ adapter: string;
+ }
+ interface Config {
+ adapters: { [index: string]: Adapter };
+ connections: { [index: string]: Connection }
+ }
+ type Ontology = {
+ collections: any;
+ }
+ interface Waterline {
+ loadCollection(collection: CollectionClass): void;
+ initialize: (config: Config, cb: (err: Error, ontology: Ontology) => any) => any;
+ collections: any;
+ }
+ interface CollectionClass {
+ (): Collection
+ }
+ // used this comment https://github.com/balderdashy/waterline/issues/1154#issuecomment-167262575
+ export type LifecycleCallbacks = {
+ beforeValidate?: { (vaues: any, next: Function): void }[] | { (vaues: any, next: Function): void };
+ beforeCreate?: { (values: any, next: Function): void }[] | { (vaues: any, next: Function): void };
+ afterCreate?: { (newlyCreatedRecord: any, next: Function): void }[] | { (newlyCreatedRecord: any, next: Function): void };
+ beforeUpdate?: { (valuesToUpdate: any, next: Function): void }[] | { (valuesToUpdate: any, next: Function): void };
+ afterUpdate?: { (valuesToUpdate: any, next: Function): void }[] | { (valuesToUpdate: any, next: Function): void };
+ beforeDestroy?: { (criteria: any, next: Function): void }[] | { (valuesToUpdate: any, next: Function): void };
+ afterDestroy?: { (destroyedInstance: any, next: Function): void }[] | { (destroyedInstance: any, next: Function): void };
+ }
+ export type CollectionDefinition = LifecycleCallbacks & {
+ attributes?: Attributes;
+ connection?: string;
+ identity?: string;
+ tableName?: string;
+ migrate?: "alter" | "drop" | "safe";
+ autoPK?: boolean;
+ autoCreatedAt?: boolean;
+ autoUpdatedAt?: boolean;
+ schema?: boolean;
+ types?: any;
+ }
+ export type Collection = CollectionDefinition;
+ export type Attributes = { [index: string]: Attribute } & {
+ toJSON?: () => string;
+ toObject?: () => any;
+ };
+ export type FunctionAttribute = () => any;
+ // Data types https://github.com/balderdashy/waterline-docs/blob/master/models/data-types-attributes.md#data-types
+ export type AttributeType = "string" | "text" | "integer" | "float" | "date" | "time"
+ | "datetime" | "boolean" | "binary" | "array" | "json";
+ export type Attribute = string | StringAttribute | EmailAttribute |
+ IntegerAttribute | FloatAttribute |
+ DateAttribute | TimeAttribute | DatetimeAttribute |
+ BooleanAttribute | BinaryAttribute | ArrayAttribute | JsonAttribute |
+ OneToOneAttribute | OneToManyAttribute | ManyToManyAttribute |
+ FunctionAttribute;
+ export type DefaultsToFn = () => T;
+ export type BaseAttribute = AttributeValidations & {
+ type?: string;
+ primaryKey?: boolean;
+ unique?: boolean;
+ required?: boolean;
+ enum?: Array;
+ size?: number;
+ columnName?: string;
+ index?: boolean;
+ defaultsTo?: T | DefaultsToFn;
+ }
+ export type StringAttribute = BaseAttribute & {
+ type: "string";
+ }
+ export type EmailAttribute = BaseAttribute & {
+ type: "email"
+ }
+ export type TextAttribute = BaseAttribute & {
+ type: "text";
+ }
+ export type IntegerAttribute = BaseAttribute & {
+ type: "integer";
+ autoIncrement?: boolean;
+ }
+ export type FloatAttribute = BaseAttribute & {
+ type: "float";
+ }
+ export type DateAttribute = BaseAttribute & {
+ type: 'date';
+ }
+ export type TimeAttribute = BaseAttribute & {
+ type: 'time';
+ }
+ export type DatetimeAttribute = BaseAttribute & {
+ type: 'datetime';
+ }
+ export type BooleanAttribute = BaseAttribute & {
+ type: 'boolean';
+ }
+ export type BinaryAttribute = BaseAttribute & {
+ type: 'binary';
+ }
+ export type ArrayAttribute = BaseAttribute & {
+ type: 'array';
+ }
+ export type JsonAttribute = BaseAttribute & {
+ type: 'json';
+ }
+ export type OneToOneAttribute = BaseAttribute & {
+ model: string;
+ }
+ export type OneToManyAttribute = BaseAttribute & {
+ collection: string;
+ via: string;
+ }
+ export type ManyToManyAttribute = BaseAttribute & {
+ collection: string;
+ via: string;
+ dominant?: boolean;
+ }
+ type AttributeValidationSyncFn = () => T;
+ type AttributeValidationAsyncFn = (cb: (value: T) => any) => void;
+
+ export type AttributeValidation = T | AttributeValidationSyncFn | AttributeValidationAsyncFn;
+ export interface AttributeValidations {
+ after?: AttributeValidation;
+ alpha?: AttributeValidation;
+ alphanumeric?: AttributeValidation;
+ array?: AttributeValidation;
+ before?: AttributeValidation;
+ boolean?: AttributeValidation,
+ contains?: AttributeValidation,
+ creditcard?: AttributeValidation,
+ date?: AttributeValidation,
+ decimal?: AttributeValidation,
+ email?: AttributeValidation,
+ empty?: AttributeValidation,
+ equals?: AttributeValidation,
+ falsey?: AttributeValidation,
+ finite?: AttributeValidation,
+ float?: AttributeValidation,
+ hexColor?: AttributeValidation,
+ hexadecimal?: AttributeValidation,
+ in?: AttributeValidation,
+ int?: AttributeValidation,
+ integer?: AttributeValidation,
+ ip?: AttributeValidation,
+ ipv4?: AttributeValidation,
+ ipv6?: AttributeValidation,
+ is?: AttributeValidation,
+ len?: AttributeValidation,
+ lowercase?: AttributeValidation,
+ max?: AttributeValidation,
+ maxLength?: AttributeValidation
+ min?: AttributeValidation,
+ minLength?: AttributeValidation,
+ not?: AttributeValidation,
+ notContains?: AttributeValidation,
+ notEmpty?: AttributeValidation,
+ notIn?: AttributeValidation,
+ notNull?: AttributeValidation,
+ notRegex?: AttributeValidation,
+ null?: AttributeValidation,
+ number?: AttributeValidation,
+ numeric?: AttributeValidation,
+ regex?: AttributeValidation,
+ required?: AttributeValidation,
+ string?: AttributeValidation,
+ truthy?: AttributeValidation,
+ undefined?: AttributeValidation,
+ uppercase?: AttributeValidation,
+ url?: AttributeValidation,
+ urlish?: AttributeValidation,
+ uuid?: AttributeValidation,
+ uuidv3?: AttributeValidation,
+ uuidv4?: AttributeValidation,
+ }
+
+ type WaterlinePromise = BluebirdPromise & {
+ exec(cb: (err: Error, result: T) => any): void;
+ }
+ type QueryBuilder = WaterlinePromise & {
+ where(condition: any): QueryBuilder;
+ limit(lim: number): QueryBuilder;
+ skip(num: number): QueryBuilder;
+ sort(criteria: string | { [attribute: string]: string }): QueryBuilder;
+ paginate(pagination?: { page: number, limit: number }): QueryBuilder;
+ populate(association: string): QueryBuilder;
+ populate(association: string, filter: any): QueryBuilder;
+ groupBy(attrOrExpr: string): QueryBuilder;
+ max(attribute: string): QueryBuilder;
+ min(attribute: string): QueryBuilder;
+ sum(attribute: string): QueryBuilder;
+ average(attribute: string): QueryBuilder;
+ }
+ interface ModelInstance {
+ id?: number | string;
+ createdAt?: Date;
+ updatedAt?: Date;
+ toJSON(): any;
+ save(): WaterlinePromise;
+ }
+ export interface Callback {
+ (err: any, result: T): any;
+ }
+ export interface Model extends ModelInstance {
+ create(params: any, cb?: Callback): WaterlinePromise;
+ create(params: any[], cb?: Callback): WaterlinePromise;
+
+ find(criteria?: any, cb?: Callback): QueryBuilder;
+
+ findOne(criteria?: any, cb?: Callback): QueryBuilder;
+
+ findOrCreate(criteria?: any, values?: any, cb?: Callback): QueryBuilder;
+
+ update(criteria: any, changes: any, cb?: Callback): WaterlinePromise;
+ update(criteria: any, changes: any[], cb?: Callback): WaterlinePromise;
+
+ destroy(criteria: any, cb?: Callback): WaterlinePromise;
+ destroy(criteria: any[], cb?: Callback): WaterlinePromise;
+
+ count(criteria: any): WaterlinePromise;
+ count(criteria: any[]): WaterlinePromise;
+
+ query(sqlQuery: string, cb: Callback): void;
+ query(sqlQuery: string, data: any, cb: Callback): void;
+
+ native(cb: (err: Error, collection: any) => void): void;
+
+ stream(criteria: any, writeEnd: any): NodeJS.WritableStream | Error;
+ }
+}
+declare interface WaterlineStatic {
+ Collection: {
+ extend: (params: Waterline.CollectionDefinition) => Waterline.CollectionClass;
+ }
+ new (): Waterline.Waterline;
+}
+declare var Waterline: WaterlineStatic;
+export = Waterline;
diff --git a/waterline/tsconfig.json b/waterline/tsconfig.json
new file mode 100644
index 0000000000..d53e4133d4
--- /dev/null
+++ b/waterline/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es6",
+ "noImplicitAny": true,
+ "strictNullChecks": true,
+ "baseUrl": "../",
+ "typeRoots": [
+ "../"
+ ],
+ "types": [
+ "node",
+ "bluebird"
+ ],
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.d.ts",
+ "waterline-tests.ts"
+ ]
+}
\ No newline at end of file
diff --git a/waterline/waterline-tests.ts b/waterline/waterline-tests.ts
new file mode 100644
index 0000000000..aeb799b9a2
--- /dev/null
+++ b/waterline/waterline-tests.ts
@@ -0,0 +1,311 @@
+import Waterline = require(".");
+const waterline = new Waterline();
+const userCollection = Waterline.Collection.extend({
+ identity: "user",
+ connection: "default",
+ attributes: {
+ firstName: "string",
+ lastName: "string",
+
+ // Add a reference to Pets
+ pets: {
+ collection: "pet",
+ via: "owner",
+ dominant: true,
+ },
+ },
+});
+const petCollection = Waterline.Collection.extend({
+ identity: "pet",
+ connection: "default",
+ attributes: {
+ breed: "string",
+ type: "string",
+ name: "string",
+
+ // Add a reference to User
+ owner: {
+ model: "user",
+ },
+ },
+});
+
+waterline.loadCollection(userCollection);
+waterline.loadCollection(petCollection);
+
+const config: Waterline.Config = {
+ adapters: {
+ memory: {},
+ },
+ connections: {
+ default: {
+ adapter: "memory",
+ },
+ },
+};
+
+waterline.initialize(config, (err, ontology) => {
+ if (err) {
+ return console.error(err);
+ }
+
+ // Tease out fully initialised models.
+ const User: Waterline.Model = ontology.collections.user;
+ const Pet: Waterline.Model = ontology.collections.pet;
+
+ User.create({ // First we create a user.
+ firstName: "Neil",
+ lastName: "Armstrong",
+ }).then((user: any) => { // Then we create the pet
+ return Pet.create({
+ breed: "beagle",
+ type: "dog",
+ name: "Astro",
+ owner: user.id,
+ });
+
+ }).then((pet) => { // Then we grab all users and their pets
+ return User.find().populate("pets");
+
+ }).then((users) => { // Results of the previous then clause are passed to the next
+ console.dir(users);
+
+ }).catch((errCatch) => { // If any errors occur execution jumps to the catch block.
+ console.error(errCatch);
+ });
+});
+
+const Person = Waterline.Collection.extend({
+ identity: "person",
+ connection: "local-postgresql",
+
+ attributes: {
+
+ // Don"t allow two objects with the same value
+ lastName: {
+ type: "string",
+ unique: true
+ },
+
+ // Ensure a value is set
+ age: {
+ type: "integer",
+ required: true
+ },
+
+ // Set a default value if no value is set
+ phoneNumber: {
+ type: "string",
+ defaultsTo: "111-222-3333"
+ },
+
+ // Create an auto-incrementing value (not supported by all datastores)
+ incrementMe: {
+ type: "integer",
+ autoIncrement: true
+ },
+
+ // Index a value for faster queries
+ emailAddress: {
+ type: "email", // Email type will get validated by the ORM
+ index: true
+ }
+ }
+});
+// https://github.com/balderdashy/waterline-docs/blob/master/models/validations.md
+const validations: Waterline.Attribute = {
+ type: "string",
+ empty: true,
+ required: true,
+ notEmpty: true,
+ undefined: true,
+ string: true,
+ alpha: true,
+ numeric: true,
+ alphanumeric: true,
+ email: true,
+ url: true,
+ urlish: true,
+ ip: true,
+ ipv4: true,
+ ipv6: true,
+ creditcard: true,
+ uuid: true,
+ uuidv3: true,
+ uuidv4: true,
+ int: true,
+ integer: true,
+ number: true,
+ finite: true,
+ decimal: true,
+ float: true,
+ falsey: true,
+ truthy: true,
+ null: true,
+ notNull: true,
+ boolean: true,
+ array: true,
+ date: true,
+ hexadecimal: true,
+ hexColor: true,
+ lowercase: true,
+ uppercase: true,
+ after: "12/12/2001",
+ before: "12/12/2001",
+ is: /ab+c/,
+ regex: /ab+c/,
+ not: /ab+c/,
+ notRegex: /ab+c/,
+ equals: 45,
+ contains: "foobar",
+ notContains: "foobar",
+ len: 35,
+ in: ["foo", "bar"],
+ notIn: ["foo", "bar"],
+ max: 24,
+ min: 4,
+ minLength: 4,
+ maxLength: 24,
+};
+const valid2 = {
+ contains: (cb: (val: string) => any) => {
+ setTimeout(() => {
+ cb("http://");
+ }, 1);
+ },
+ before: () => {
+ return this.endDate;
+ },
+ after: () => {
+ return this.startDate;
+ }
+};
+const model: Waterline.CollectionDefinition = {
+ attributes: {
+ email: {
+ type: "email",
+ special: true // ignored by validation
+ },
+ cousins: {
+ collection: "related",
+ via: "property",
+ async: true // ignored by validation
+ }
+ }
+};
+// Lifecycle Callbacks https://github.com/balderdashy/waterline-docs/blob/master/models/lifecycle-callbacks.md
+
+const attr1: Waterline.CollectionDefinition = {
+ beforeValidate: (values, next) => {
+ next();
+ next("");
+ },
+ beforeCreate: (values, next) => {
+ next(new Error(""));
+ next();
+ },
+ afterCreate: (values, next) => {
+ next(new Error(""));
+ next();
+ },
+ beforeUpdate: (values, next) => {
+ next(new Error(""));
+ next();
+ },
+ afterUpdate: (values, next) => {
+ next(new Error(""));
+ next();
+ },
+ beforeDestroy: (values, next) => {
+ next(new Error(""));
+ next();
+ },
+ afterDestroy: (values, next) => {
+ next(new Error(""));
+ next();
+ },
+};
+// Queries https://github.com/balderdashy/waterline-docs/blob/master/queries/query.md
+let User: Waterline.Model = {} as any;
+User.find()
+ .where({ name: { contains: "foo" } })
+ .populate("animals", { type: "dog", limit: 10 })
+ .skip(20)
+ .limit(10)
+ .exec((err, users) => {
+ users.map((u) => u.any);
+ });
+let Comment: Waterline.Model = {} as any;
+User.findOne()
+ .where({ id: 2 })
+ .then((user) => {
+ const comments = Comment.find({ userId: user.id }).then((comments2) => {
+ return comments2;
+ });
+
+ return [user.id, user.friendsList, comments];
+ })
+ .spread((userId, friendsList, comments) => {
+
+ })
+ .catch((err: any) => {
+ // An error occured
+ });
+
+User.find()
+ .where({ name: { startsWith: "w" } })
+ .exec((err, results) => {
+ throw err;
+ });
+// Simple Population
+User.find()
+ .populate("foo")
+ .exec((err, users) => { });
+// Collection Filtering
+User.find()
+ .populate("foo", { type: "bar", limit: 20 })
+ .exec((err, users) => { });
+User.find()
+ .limit(10)
+ .exec((err, users) => { });
+User.find()
+ .skip(10)
+ .exec((err, users) => { });
+User.find()
+ .skip(10)
+ .limit(10)
+ .exec((err, users) => { });
+User.find()
+ .paginate({ page: 2, limit: 10 })
+ .exec((err, users) => { });
+User.find().sort("roleId asc")
+ .sort({ createdAt: "desc" }).exec((err, users) => { });
+User.find().exec((err, users) => { });
+// Query methods https://github.com/balderdashy/waterline-docs/blob/master/queries/query-methods.md
+// .find( criteria, [callback] )
+User.find(1, (err, values) => { values.map((v) => v); });
+User.find({ name: "Walter Jr" }).exec((err, users) => { users.map((u) => u.id); });
+// .findOne( criteria, [callback] )
+User.findOne({ name: "Walter Jr" }).exec((err, users) => { users.map((u: any) => u.id); });
+User.findOne(1).exec((err, users) => { users.map((u: any) => u.id); });
+User.findOne("1").exec((err, users) => { users.map((u: any) => u.id); });
+User.findOne(1, (err, value) => { });
+// .create( criteria, [callback] )
+User.create({ name: "Walter Jr" }).exec((err, user) => { });
+User.findOrCreate({ name: "Walter Jr" }, {}, (err, user) => { }).exec((err, users) => { });
+// .update( search criteria , values , [callback] )
+User.update({ name: "Walter Jr" }, { name: "Flynn" }, (err, value) => { }).exec((err, users) => { });
+// .destroy( criteria , [callback] )
+User.destroy({ name: "Flynn" }, (err, value) => { }).exec((err) => { });
+// .query( query, [data], callback )
+const Movie: Waterline.Model = {} as any;
+const title = "The Speech";
+Movie.query("SELECT * FROM movie WHERE title = $1", [title], (err, results) => { });
+// Aggregates https://github.com/balderdashy/waterline-docs/blob/master/queries/query-methods.md#aggregates
+Movie.find()
+ .groupBy("genre")
+ .max("revenue")
+ .min("title")
+ .sum("imdb")
+ .average("cost")
+ .then((results: any) => { });