npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@themost/client

v2.16.3

Published

MOST Web Framework Codename Blueshift - Client Common

Downloads

462

Readme

npm GitHub top language License GitHub last commit GitHub Release Date npm Snyk Vulnerabilities for npm package

@themost/client

MOST Web Framework Logo

@themost-framework core module for javascript clients.

@themost/client provides a set of methods for creating OData v4 queries by using javascript closures in both client and server.

e.g. get name and price of products with category equals to 'Laptops'

// GET /Products?$select=name,price&$filter=category eq 'Laptops'

const items = await context.model('Products').select(({name, price}) => {
    return {
        name,
        price
    }
}).where(({category}) => {
    return category === 'Laptops'
}).getItems();

Javascript closure prototypes introduced by @themost/query uses native language and produces equivalent query expressions for both client and server environments:

import { round } from '@themost/query';

context.model('Products').select((x) => {
    return {
        name: x.name,
        releaseYear: x.releaseDate.getFullYear(),
        price: round(x.price, 2)
    }
}).where((x) => {
    return x.category === 'Laptops';
})
...

which produces the following OData expression /Products?$select=name,year(releaseDate) as releaseYear,round(price,2) as price&$filter=category eq 'Laptops'

or an equivalent SQL statement for server-side enviroments SELECT Products.name AS name, YEAR(Products.releaseDate) AS releaseYear, ROUND(Products.price,2) AS price FROM Products WHERE Products.category = 'Laptops'

node.js client

@themost/node

@themost/node is a client module for node.js applications which are going to use @themost-framework as backend api server.

angular client

@themost/angular

@themost/angular is a client module for angular 2.x+ applications which are going to use @themost-framework as backend api server.

react client

@themost/react

@themost/react is a client module for react applications which are going to use @themost-framework as backend api server.

jQuery client

@themost/jquery

@themost/jquery is a client module for JQuery scripts and applications which are going to use @themost-framework as backend api server.

Usage

use ClientDataContext which is being provided by your environment and initialize an instance of ClientDataQueryable class.

System Query Options

Read OData v4 specification for more information about system query options:

http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#_Toc31360955

select(expr: QueryFunc, ...params: any[])

Define $select system query option by using a javascript closure:

const items = await context.model('Orders')
    .asQueryable()
    .select((x) => {
        return {
            id: x.id,
            customer: x.customer.description,
            orderDate: x.orderDate,
            product: x.orderedItem.name
        }
    })
    .where((x) => {
        return x.paymentMethod.alternateName === 'DirectDebit';
    }).orderByDescending((x) => x.orderDate)
    .take(10)
    .getItems();

/Orders?$select=id,customer/description as customer,orderDate,orderedItem/name as product&$filter=paymentMethod/alternateName eq 'DirectDebit'&$orderby=orderDate desc&$top=10

where(expr: QueryFunc, ...params: any[])

Define $filter system query option by using a javascript closure:

const items = await context.model('Orders')
    .asQueryable()
    .where((x, orderStatus) => {
        return x.orderStatus.alternateName === orderStatus;
    }, 'OrderPickup').take(10)
    .getItems();

/Orders?$filter=orderStatus/alternateName eq 'OrderPickup'&$top=10

Using parameters

A query expression can accept parameters as additional arguments. The following example demonstrates how to use parameters in a query expression e.g.

const items = await context.model('Orders')
    .asQueryable()
    .where((x, orderStatus) => {
        return x.orderStatus.alternateName === orderStatus;
    }, 'OrderPickup').take(10)
    .getItems();

where the first parameter is a query closure and the second parameter is a string value which is going to be passed to closure as orderStatus argument.

const items = await context.model('Orders')
    .asQueryable()
    .where((x, orderStatus, productCategory) => {
        return x.orderStatus.alternateName === orderStatus &&
            x.orderedItem.category === productCategory;
    }, 'OrderPickup', 'Desktops').take(10)
    .getItems();

Logical Operators

Use logical operators while querying data:

const items = await context.model('Products')
    .asQueryable()
    .where(({category}) => {
        return category === 'Laptops' ||
            category === 'Desktops';
    }).getItems();

/People?$filter=(category eq 'Laptops' or category eq 'Desktops')

import { round } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .where(({category, price}) => {
        return category === 'Laptops' && price <=900;
    }).getItems();

/People?$filter=(category eq 'Laptops' and price le 900)

Comparison operators

@themost/client supports the usage of OData comparison operators like eq, ne, lt, le etc

equals
const items = await context.model('Orders')
    .asQueryable()
    .where(({id}) => {
        return id === 100;
    }).getItem();

/Orders?$filter=id eq 100

not equals
const item = await context.model('Orders')
    .asQueryable()
    .where(({category}) => {
        return category !== 'Desktops';
    }).getItems();

/Orders?$filter=category ne 'Desktops'

greater than
const items = await context.model('Orders')
    .asQueryable()
    .where(({category, price}) => {
        return category === 'Desktops' && price > 1000;
    }).getItems();

/Orders?$filter=(category eq 'Desktops' and price gt 1000)

greater than or equal
const item = await context.model('Orders')
    .asQueryable()
    .where(({category, price}) => {
        return category === 'Desktops' && price >= 1000;
    }).getItems();

/Orders?$filter=(category eq 'Desktops' and price ge 1000)

lower than
const items = await context.model('Orders')
    .asQueryable()
    .where(({category, price}) => {
        return category === 'Desktops' && price < 1200;
    }).getItems();

/Orders?$filter=(category eq 'Desktops' and price lt 1200)

lower than or equal
const items = await context.model('Orders')
    .asQueryable()
    .where(({category, price}) => {
        return category === 'Desktops' && price <= 1200;
    }).getItems();

/Orders?$filter=(category eq 'Desktops' and price le 1200)

Aggregate functions

@themost/client supports the usage of aggregate functions like count, min, max for getting aggregated results

count
import { count } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .select((x) => {
        return {
            category: x.category,
            total: count(x.id)
        };
    }).groupBy((x) => x.category)
    .getItems();

/Products?$select=category,count(id) as total&$groupby=category

min
import { min } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .select((x) => {
        return {
            category: x.category,
            minimumPrice: min(x.price)
        };
    }).groupBy((x) => x.category)
    .getItems();

/Products?$select=category,min(price) as minimumPrice&$groupby=category

min
import { max } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .select((x) => {
        return {
            category: x.category,
            maxPrice: max(x.price)
        };
    }).groupBy((x) => x.category)
    .getItems();

/Products?$select=category,max(price) as maxPrice&$groupby=category

String functions

@themost/client supports the usage of string functions while querying data

indexof
const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return x.name.indexOf('Intel') >= 0;
    })
    .getItems();

/Products?$filter=indexof(name,'Intel') ge 0

startsWith
const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return x.name.startsWith('Intel') === true;
    })
    .getItems();

/Products?$filter=startswith(name,'Intel') eq true

endsWith
const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return x.name.endsWith('Edition') === true;
    })
    .getItems();

/Products?$filter=endswith(name,'Edition') eq true

toLowerCase
const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return x.category.toLowerCase() === 'laptops';
    })
    .getItems();

/Products?$filter=tolower(category) eq 'laptops'

toUpperCase
const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return x.category.toUpperCase() === 'LAPTOPS';
    })
    .getItems();

/Products?$filter=toupper(category) eq 'LAPTOPS'

substring
const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return x.category.substring(0,3) === 'Lapt';
    })
    .getItems();

/Products?$filter=substring(category,0,3) eq 'Lapt'

Date functions

@themost/client supports also the usage of date functions while querying data

getDate
const items = await context.model('Orders')
    .asQueryable()
    .where((x) => {
        return x.orderDate.getDate() === 0;
    })
    .getItems();

/Orders?$filter=day(orderDate) eq 19

getMonth
const items = await context.model('Orders')
    .asQueryable()
    .where((x) => {
        return x.orderDate.getMonth() === 0;
    })
    .getItems();

/Orders?$filter=(month(orderDate) sub 1) eq 0

getFullYear
const items = await context.model('Orders')
    .asQueryable()
    .where((x) => {
        return x.orderDate.getFullYear() === 2019;
    })
    .getItems();

/Orders?$filter=(month(orderDate) sub 1) eq 0

getHours
const items = await context.model('Orders')
    .asQueryable()
    .where((x) => {
        return x.orderDate.getHours() === 14;
    })
    .getItems();

/Orders?$filter=hour(orderDate) eq 14

getMinutes
const items = await context.model('Orders')
    .asQueryable()
    .where((x) => {
        return x.orderDate.getMinutes() === 30;
    })
    .getItems();

/Orders?$filter=minute(orderDate) eq 30

getSeconds
const items = await context.model('Orders')
    .asQueryable()
    .where((x) => {
        return x.orderDate.getSeconds() === 30;
    })
    .getItems();

/Orders?$filter=second(orderDate) eq 30

Math Functions

floor

const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return Math.floor(x.price) <= 177;
    })
    .getItems();

/Products?$filter=floor(price) le 177

ceil

const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return Math.ceil(x.price) >= 177;
    })
    .getItems();

/Products?$filter=floor(price) ge 177

round

import { round } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return round(x.price, 2) >= 177;
    })
    .getItems();

/Products?$filter=round(price, 2) ge 177

Arithmetic operators

add

import { round } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return round(x.price, 2) + 100 >= 277;
    })
    .getItems();

/Products?$filter=(round(price,2) add 100) ge 277

subtract

import { round } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return round(x.price, 2) - 100 <= 277;
    })
    .getItems();

/Products?$filter=(round(price,2) sub 100) le 277

multiply

import { round } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return round(x.price, 2) * 0.75 < 800;
    })
    .getItems();

/Products?$filter=(round(price,2) mul 0.75) lt 800

divide

import { round } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .where((x) => {
        return round(x.price, 2) / 1.25 < 800;
    })
    .getItems();

/Products?$filter=(round(price,2) div 1.25) lt 800

case

import { round } from '@themost/query';

const items = await context.model('Products')
    .asQueryable()
    .select(({name, price}) => {
        return {
            name: name,
            value: price < 800 ? 'Normal' : 'Expensive'
        }
    })
    .where(({category}) => {
        return category === 'Laptops';
    })
    .getItems();

/Products?$select=name,case(price lt 800:'Normal',true:'Expensive') as value&$filter=category eq 'Laptops'

take(n: number)

Set $top system query option for defining the number of records to be taken

const items = await context.model('Orders')
    .asQueryable()
    .where((x, orderStatus) => {
        return x.orderStatus.alternateName === orderStatus;
    }, 'OrderPickup').take(10)
    .getItems();

/Orders?$filter=orderStatus/alternateName eq 'OrderPickup'&$top=10

skip(n: number)

Set $skip system query option for defining the number of records to be skipped

const items = await context.model('Orders')
    .asQueryable()
    .where((x, orderStatus) => {
        return x.orderStatus.alternateName === orderStatus;
    }, 'OrderPickup').take(25)
    .skip(25)
    .getItems();

/Orders?$filter=orderStatus/alternateName eq 'OrderPickup'&$top=25&$skip=25

orderBy(expr: QueryFunc, ...params: any[])

Define $orderby system query option for sorting records

const items = await context.model('People')
    .asQueryable()
    .orderBy(({familyName}) => familyName)
    .getItems();

/People?$orderby=familyName

thenBy(expr: QueryFunc, ...params: any[])

const items = await context.model('People')
    .asQueryable()
    .orderBy(({familyName}) => familyName)
    .thenBy(({givenName}) => givenName)
    .getItems();

/People?$orderby=familyName,givenName

orderByDescending(expr: QueryFunc, ...params: any[])

const items = await context.model('People')
    .asQueryable()
    .orderByDescending(({familyName}) => familyName)
    .getItems();

/People?$orderby=familyName desc

thenByDescending(expr: QueryFunc, ...params: any[])

const items = await context.model('People')
    .asQueryable()
    .orderByDescending(({familyName}) => familyName)
    .thenByDescending(({givenName}) => givenName)
    .getItems();

/People?$orderby=familyName desc,givenName desc

groupBy(...arg: [QueryFunc], params?: any)

Define $groupby system query option to group records by using javascript closures:

const results = await context.model('Orders')
    .asQueryable()
    .select(({id, orderStatus}) => {
        return {
            total: count(id),
            orderStatus
        }
    }).groupBy(({orderStatus}) => orderStatus)
    .getItems();

/Orders?$select=count(id) as total,orderStatus&$groupby=orderStatus

expand(...args: (OpenDataQuery | QueryFunc)[])

Define $expand system query option for getting nested objects

Read more about $expand at http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#_Toc31361039

const items= await context.model('Orders')
    .asQueryable()
    .select(({id, orderStatus, orderDate}) => {
        return {
            id,
            orderStatus,
            orderDate
        }
    }).expand(
        (x) => x.customer,
        (x) => x.orderedItem
    ).getItems();

/Orders?$select=id,orderStatus,orderDate&$expand=customer,orderedItem

or use query expressions for applying nested query options:

import { any } from '@themost/query';

const items= await context.model('People')
    .asQueryable()
    .expand(
        any((x) => x.address)
        .select(({id, streetAddress, addressLocalilty}) => ({
            id, streetAddress, addressLocalilty
        }))
    ).getItems();

/People?$expand=address($select=id,streetAddress,addressLocalilty;$expand=addressCountry)

Using CLI

@themost/client provides a command line interface for generating client-side type declarations from an OData metadata service.

Connect to an OData service and generate client-side type declarations:

$ npx @themost/client http://localhost:3000/api/

or extract metadata from an OData metadata document:

$ npx @themost/client ./metadata.xml

Use --out-file option for specifying the output file:

$ npx @themost/client http://localhost:3000/api/ --out-file ./client.d.ts