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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@andrei.caminschi/f-orm

v1.0.8

Published

My webpack project

Downloads

45

Readme

(F)rontend ORM

f-orm is a library that brings ORM to frontend.

API

The library comes with a preloaded api wrapper around axios that allows calls to the API After loading the library call the following lines

import {fOrm} from '@andrei.caminschi/f-orm';
fOrm.SetApiBaseUrl('http://api.your-domain.com').SetApiVersion('1.0');

Authentication is done via tokens. After logging in the user call

fOrm.GetDefaultApiDriver().SetToken('the-secret-token');
// now all the requests will have the header "Authorization: Bearer the-secret-token"

Models

Models are classes that encapsulate CRUD methods. Communication with the database is done via API

API Requirements

The library expects the following endpoints to be available ( exemplified for the user model) POST /user - creates a new user PATCH /user/10 - modifies the user with the id 10 DELETE /user/10 - deletes the user with id 10 GET /user/10 - gets info about the user with id 10

All the endpoints ( except delete) should return the following response format ( exemplified for the user model):

{
  "success": boolean,
  "data" : {
    "user" : {
      "id": "the id",
      "email": "the email of the user",
      ...
    }   
  },
  "message" : string, // not required, it can be used to display error messages to the user
  "validation-errors" : { // not required, only fill the fields that failed validation
    "field-name" : "Error message"
  }
}

Model declaration example

import {Dictionary, HasMany, HasOne, IDatabaseRecord, Model, RECORD_INFO, RELATIONS, Repository} from '@andrei.caminschi/f-orm';
   // general information about the model
   let UserRecord: IDatabaseRecord<UserModel> = {
       Name: 'user', // name of a single instance ( row )
       Table: 'users', // name of the table 
       PrimaryKey: 'Id', // primary key to be used
       Relations: {}, // just leave it like this, it'll be explained later
       Namespace: '', // prefix for the api url generation
       Make(data?: Dictionary<any>) {return new UserModel(data)} // Factory to generate a new instance of a model
   };
   
   // Model declaration
   export class UserModel extends Model {
       // Copy these over
       static [RECORD_INFO]() {return UserRecord;}
       [RECORD_INFO]() {return UserModel[RECORD_INFO]();}
       [RELATIONS]() {return this.relations;}
   
       // The columns of the model
       public Id: number = 0;
       public Email:string = '';
       public Name: string = '';
       public Password:string = '';
   
       // Leave this as it is
       constructor(data?: Dictionary<any>) {
           super(data);
           if (data) this.Load(data);
           this.LoadOriginalAttributes();
       }
   }
   // Repository declaration
   // A repository contains multiple Models
   export class UsersRepository extends Repository<UserModel> {
       static [RECORD_INFO]() {return UserRecord;}
       [RECORD_INFO]() {return UserModel[RECORD_INFO]();}
   }
Code example

// creating a new user
let user = new UserModel();
user.Email = '[email protected]'
user.Name = 'Andrei';
user.Password = 'secret';
user.Save(); // calls the create endpoint, and loads the data from the response
 
//retrieve info about an user
let user = new UserModel();
user.Id = 10;
user.Get(); // call the get info endopoint and loads the data from the response

Methods

Get(extra?: Dictionary<any>):Promise<IApiResponse>

Gets the model data from the API.

Save(extra?: (Model | Dictionary<any>)):Promise<IApiResponse>

Calls the create or patch endpoint url with only the changed attributes. If extra is a dictionary, it will be appended to the request If extra is a model, the properties will be loaded and after that saved ( usefull for relations)

After the request is finished, the data from the response is loaded into the model

HasChanged():boolean

Determines if the model attributes have changed since the last time it was loaded

HasAttributeChanged(key: string):boolean

Determines if the attribute value has changed

ToJson():Dictionary<any>

Returns a JSON representation of the model. All the property names will be converted from CamelCase to snake_case.

Relations

All the relations have one parameter of type RelationOptions

type RelationOptions = {
    /**
     * The local key to be used when generating the URL
     */
    LocalKey?: string,
    /**
     * The foreign key to be used when generating the URL
     */
    ForeignKey?: string,
    /**
     * Transforms the URL of the relation target to eloquent
     * Eg. instead of /posts?user_id=10 it will generate user/10/posts
     */
    UseEloquentUrl?: boolean
}
BelongsTo

Creates a BelongsTo relation

export class UserModel extends Model {
    ....
    
    @BelongsTo() Group(){return new GroupModel()}
}

let user = new UserModel();
user.Id = 10;
console.log(user.Group().Name); // will get the group of the user with id 10 
HasMany

Creates a HasMany relation

export class UserModel extends Model {
    ....
    
    @HasMany() Posts(){return new PostsRepository()}
}

let user = new UserModel();
user.Id = 10;
user.Posts().Get(); // explained below, gets all the posts belonging to the user with id 10
console.log(user.Posts().Items);   
HasOne

Creates a HasMany relation

export class UserModel extends Model {
    ....
    
    @HasOne() Avatar(){return new AvatarModel()}
}

let user = new UserModel();
user.Id = 10;
let avatar = new AvatarModel();
avatar.Url = 'tralalala';
user.Avatar().Save(avatar); 

Repositories

The repository is a table, contains multiple models and provides methods for filtering, sorting and paginating

Required endpoints ( exemplified for users)

GET /users - searches for users

The endpoint should return the following response

{
  "success": boolean,
  "data" : {
    "count": number, // the total number of records that match the filters
    "users" : [
      {
        "id": "the first id",
        "email": "the email of the user",
        ...
      },
      {
        "id": "the id",
        "email": "the email of the user",
        ...
      },
      ....
    ],
  },
  "message" : string, // not required, it can be used to display error messages to the user
  }

Methods

Get(append?: string, extra?: Dictionary<any>):Promise<IApiResponse> Calls the search endpoint and loads the data

append will be appended to the url extra is the extra data to be send, apended to the query

The results are present in the Items property of the class, and they are all casted to Model

Filtering

ResetFilters()

Resets all the filters, except the fixed ones

SortBy(column:string,desc:bool) Sends the following query params to the API endpoint sort-by=column;DESC|ASC

Skip(count:number) & Take(count:number) & Limit(count:number) Sets the limit for the api call The resulting query parameter is limit=skip,take ForPage(page: number, per_page: number = 15) paginates for the requested page using Skip and Take

WhereEquals(field: string, value: any, is_fixed_filter: boolean = false); // generates query parameter field=value
WhereNotEquals(field: string, value: any, is_fixed_filter: boolean = false); // generates query parameter field-NOTEQ=value
WhereGreaterThan(field: string, value: any, is_fixed_filter: boolean = false); // generates query parameter field-GT=value
WhereGreaterThanOrEquals(field: string, value: any, is_fixed_filter: boolean = false); // generates query parameter field-GTE=value
WhereLessThan(field: string, value: any, is_fixed_filter: boolean = false); // generates query parameter field-LT=value
WhereLessThanOrEquals(field: string, value: any, is_fixed_filter: boolean = false); // generates query parameter field-LTE=value
WhereIsNull(field: string, is_fixed_filter: boolean = false); // generates query parameter field-NULL=null
WhereIsNotNull(field: string, is_fixed_filter: boolean = false); // generates query parameter field-NOTNULL=null
WhereBetween(field: string, value: any[], is_fixed_filter: boolean = false); // generates query parameter field-BETWEEN=value1,value2
WhereNotBetween(field: string, value: any[], is_fixed_filter: boolean = false); // generates query parameter field-NOTBETWEEN=value1,value2
WhereIn(field: string, value: any[], is_fixed_filter: boolean = false); // generates query parameter field-IN=value1,value2,...,valueN
WhereNotIn(field: string, value: any[], is_fixed_filter: boolean = false); // generates query parameter field-NOTIN=value1,value2,...,valueN
WhereStartsWith(field: string, value: string, is_fixed_filter: boolean = false); // generates query parameter field-STARTSWITH=value
WhereEndsWith(field: string, value: string, is_fixed_filter: boolean = false); // generates query parameter field-ENDSWITH=value
WhereContains(field: string, value: string, is_fixed_filter: boolean = false); // generates query parameter field-CONTAINS=value

Examples ( for the user case)

let repo = new UsersRepository();
repo.WherContains('name','andrei')
    .WhereEquals('email','[email protected]')
    .WhereGreaterThanOrEquals('created_at','2019-09-09')
    .ForPage(1)
    .SortBy('name')
    .Get()

// resulting query is
// GET /users?name-CONTAINS=andrei&[email protected]&created_at-GTE=2019-09-09&limit=0,15&sort-by=name|ASC
Additional methods

AddItem(item:Model) - manually adds an item to the repo

AddItemFromData(data:Dictionary<any>) - creates a new model and adds it

Save(item:Model) - adds the item to the repo and saves it ( usually used for relations, that automatically configure the model)