import { escape , formatDate } from "./grammar" ; export interface IStringable { toString : ( ) => string ; } export interface IBaseExpression < T > { /**
     * Inserts a tag name in the expression.
     */ tag : ( name : string ) => T ; /**
     * Inserts a field name in the expression.
     */ field : ( name : string ) => T ; /**
     * Chains on a value to the expression. An error will be thrown if the
     * value is a type we can't represent in InfluxQL, primarily `null` or
     * `undefined.`
     */ value : ( value : any ) => T ; } export interface IExpressionHead extends IBaseExpression < IBinaryOp > { } export interface IExpressionTail extends IBaseExpression < IExpressionHead > { } export interface IBinaryOp { /**
     * Adds an 'AND' operator
     */ and : IExpressionTail ; /**
     * Adds an 'OR' operator
     */ or : IExpressionTail ; /**
     * Adds a '+' addition symbol
     */ plus : IExpressionTail ; /**
     * Adds a '*' multiplication symbol
     */ times : IExpressionTail ; /**
     * Adds a '-' subtraction symbol
     */ minus : IExpressionTail ; /**
     * Adds a '/' division symbol
     */ div : IExpressionTail ; /**
     * Adds a '=' symbol
     */ equals : IExpressionTail ; /**
     * Adds a '=~' comparator to select entries matching a regex.
     */ matches : IExpressionTail ; /**
     * Adds a '!~' comparator to select entries not matching a regex.
     */ doesntMatch : IExpressionTail ; /**
     * Adds a '!=' comparator to select entries not equaling a certain value.
     */ notEqual : IExpressionTail ; /**
     * Adds a '>' symbol
     */ gt : IExpressionTail ; /**
     * Adds a '>=' symbol
     */ gte : IExpressionTail ; /**
     * Adds a '<' symbol
     */ lt : IExpressionTail ; /**
     * Adds a '<=' symbol
     */ lte : IExpressionTail ; } function regexHasFlags ( re ) { if ( typeof re . flags !== "undefined" ) { return re . flags . length > 0 ; } return ! re . toString ( ) . endsWith ( "/" ) ; } example export class Expression implements IExpressionHead , IExpressionTail , IBinaryOp { private readonly _query : string [ ] = [ ] ; param name return public tag ( name ) { this . field ( name ) ; return this ; } param name return public field ( name ) { this . _query . push ( escape . quoted ( name ) ) ; return this ; } param fn return example public exp ( fn ) { this . _query . push ( "(" + fn ( new Expression ( ) ) . toString ( ) + ")" ) ; return this ; } param value return public value ( value ) { switch ( typeof value ) { case "number" : this . _query . push ( value . toString ( ) ) ; return this ; case "string" : this . _query . push ( escape . stringLit ( value ) ) ; return this ; case "boolean" : this . _query . push ( value ? "TRUE" : "FALSE" ) ; return this ; default : if ( value instanceof Date ) { this . _query . push ( formatDate ( value ) ) ; return this ; } if ( value instanceof RegExp ) { if ( regexHasFlags ( value ) ) { throw new Error ( "Attempted to query using a regex with flags, " + "but Influx doesn't support flags in queries." ) ; } this . _query . push ( "/" + value . source + "/" ) ; return this ; } if ( value && typeof value . toString === "function" ) { this . _query . push ( value . toString ( ) ) ; return this ; } throw new Error ( "node-influx doesn't know how to encode the provided value into a " + "query. If you think this is a bug, open an issue here: https://git.io/influx-err" ) ; } } /**
     * Chains on an AND clause to the expression.
     */ get and ( ) : this { this . _query . push ( "AND" ) ; return this ; } /**
     * Chains on an OR clause to the expression.
     */ get or ( ) : this { this . _query . push ( "OR" ) ; return this ; } /**
     * Chains on a `+` operator to the expression.
     */ get plus ( ) : this { this . _query . push ( "+" ) ; return this ; } /**
     * Chains on a `*` operator to the expression.
     */ get times ( ) : this { this . _query . push ( "*" ) ; return this ; } /**
     * Chains on a `-` operator to the expression.
     */ get minus ( ) : this { this . _query . push ( "-" ) ; return this ; } /**
     * Chains on a `/` operator to the expression.
     */ get div ( ) : this { this . _query . push ( "/" ) ; return this ; } /**
     * Chains on a `=` conditional to the expression.
     */ get equals ( ) : this { this . _query . push ( "=" ) ; return this ; } /**
     * Chains on a `=~` conditional to the expression to match regexes.
     */ get matches ( ) : this { this . _query . push ( "=~" ) ; return this ; } /**
     * Chains on a `!`` conditional to the expression to match regexes.
     */ get doesntMatch ( ) : this { this . _query . push ( "!~" ) ; return this ; } /**
     * Chains on a `!=` conditional to the expression.
     */ get notEqual ( ) : this { this . _query . push ( "!=" ) ; return this ; } /**
     * Chains on a `>` conditional to the expression.
     */ get gt ( ) : this { this . _query . push ( ">" ) ; return this ; } /**
     * Chains on a `>=` conditional to the expression.
     */ get gte ( ) : this { this . _query . push ( ">=" ) ; return this ; } /**
     * Chains on a `<` conditional to the expression.
     */ get lt ( ) : this { this . _query . push ( "<" ) ; return this ; } /**
     * Chains on a `<=` conditional to the expression.
     */ get lte ( ) : this { this . _query . push ( "<=" ) ; return this ; } return public toString ( ) { return this . _query . join ( " " ) ; } } example export class Measurement { private _parts : string [ ] = [ null , null , null ] ; param name return public name ( name ) { this . _parts [ 2 ] = name ; return this ; } param retentionPolicy return public policy ( retentionPolicy ) { this . _parts [ 1 ] = retentionPolicy ; return this ; } param db return public db ( db ) { this . _parts [ 0 ] = db ; return this ; } return throws public toString ( ) { if ( ! this . _parts [ 2 ] ) { throw new Error ( `You must specify a measurement name to query! Got \`${ this . _parts [ 2 ] }\`` ) ; } return this . _parts . filter ( ( p ) => Boolean ( p ) ) . map ( ( p ) => escape . quoted ( p ) ) . join ( "." ) ; } } export type measurement = { measurement : string | ( ( m : Measurement ) => IStringable ) ; } ; export type where = { where : string | ( ( e : IExpressionHead ) => IStringable ) ; } ; export function parseMeasurement ( q ) { if ( typeof q . measurement === "function" ) { return q . measurement ( new Measurement ( ) ) . toString ( ) ; } return q . measurement ; } export function parseWhere ( q ) { if ( typeof q . where === "function" ) { return q . where ( new Expression ( ) ) . toString ( ) ; } return q . where ; }