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

jsmetabackend

v1.0.58

Published

Backend js Framework

Downloads

15

Readme

it

myKode Backend

myKode Backend is a set of Node.js classes accompanied by a minimal backend designed to minimize the development time of a Node.js application.

The framework's classes are designed to access various relational databases interchangeably. The chosen structure for managing data sets in memory is jsDataSet, a class similar to .NET's DataSets, where DataRow objects are much like plain objects but retain the original state of the row, i.e., the state after the last acceptChanges (a method that makes changes permanent) or rejectChanges (a method that cancels changes to the row).

The class jsDataQuery is used to represent filters and expressions, and its instances can be applied interchangeably to database tables or any collection of JavaScript objects, especially to DataRow objects of a DataSet.

Classes are provided for managing different applications and databases.

jsApplication

jsApplication is the general prototype of the application at its highest level.

It is possible to integrate or modify its various methods to customize them according to specific needs.

Authentication

Authentication is managed through JSON Web Tokens (JWT). Each user is associated with a session identified by a code that the client must send in every request, in the encrypted JWT token.

jsApplication handles creating a context (Context) for each request and destroying it when the request is fulfilled. It creates the environment of the connected user with information such as their role and permissions.

It also creates routes and ensures access is granted only to clients providing an appropriate token in the request header unless the route has been specifically configured with the getNoTokenFolders function. getNoTokenFolders is a method of jsApplication defined simply as:

getNoTokenFolders: function(){
    return {
        "auth": true
    };
}

This allows access (only) to the "auth" folder without requiring a valid token. Even unauthenticated requests must provide a fictitious, "anonymous" token, the value of which is configured in the config/tokenConfig file under the AnonymousToken property.

In the HTTP header of each client request, there must be a line like:

Authorization: Bearer <token>

Where <token> is either the "anonymous" token or a token issued by the application upon authentication.

jsApplication decodes the token for each request and sets the data obtained from the req.headers.authorization property of the request req. This way, all routes can access it.

The token is verified and decoded in the req.auth field (configurable in tokenConfig.options.requestProperty). In general, req.auth will contain an object of type Token. A simple example of an authentication route can be found in the login module.

Upon startup, a jsApplication creates an ExpressApplication and an Express.Router. For each subfolder in the routes/ folder, it reads the files inside it and associates a router with each one that responds to the request /folder/fileName, provided that the file is a node module whose file name does not start with an underscore and exposes a router as its only exported property. This makes it easy to add a new route by exposing it in a node module inside a subfolder of routes, regardless of the type of service (GET/POST) and its parameters.

It also handles authenticating the user and providing an anonymous context if not authenticated yet. For each connected user, it establishes a session identified with a sessionID.

Each database is identified by a dbCode, and jsApplication is associated with a database and creates a connection pool to make access more efficient. When a request arrives, a connection is taken from the pool if one is available.

Data Access

To read/write data from/to the database, invoke stored procedures, or perform any other operation, there are three main classes: DataAccess, GetData, and PostData.

  • DataAccess is used for low-level operations, such as sending simple read or write commands.
  • GetData is used to read entire DataSets or parts of them.
  • PostData is used to write entire DataSets.

Business Logic

jsBusinessLogic is the class responsible for invoking business rules. These rules are essentially SQL checks applied to each individual row written to the database. The text of the checks is stored in some configuration tables. The rules are "compiled" by an external tool into database stored procedures and invoked when saving data. If the configuration tables contain no rows, no checks will be applied.

Security

The class jsSecurity is queried by the PostData class during the data saving phase. The rules are stored as textual conditions in the customgroupoperation table.

For details, refer to the jsDoc and the summary.

DataSet

The DataSets of the application are stored in JSON format in the client/dataset folder. The JSON follows the format used for serializing the jsDataSet class, based on the serialize and deserialize methods.

Serialization also includes the state of DataRow with current values and original values for rows in the modified state.

When creating a DataSet, all DataTables with all necessary DataColumn and DataRelation that link the included DataTables must be inserted. This is especially important for navigation when extracting data using the GetData class.

The basic assumption is that there is a "main" table of the DataSet and a set of "subentity" tables representing its details. Then there are parent tables of the entity and subentity tables, whose rows are read as needed based on the data present in the first set.

The subentity relationship is logically identified by the fact that it cannot exist in any way without the entity (table) of which it is a detail. This must be formalized through keys; the subentity must include in its key fields all key fields of the entity and must be related with a DataRelation in the DataSet. It is possible to have subentities at a lower level without any limit.

Satellite tables can also be present, i.e., tables that are parents of entity and subentity tables.

To create a DataSet, several methods can be used:

Manual creation of a DataSet

You can instantiate a DataSet and then add tables and columns to them. This is a bit cumbersome unless a code generator is used to update the code based on any changes to the table structure.

Example:

let d = new DataSet();
let tOrder = d.newTable("order");
tOrder.setDataColumn("idorder", CType.int);
tOrder.setDataColumn("name", CType.string);
tOrder.setDataColumn("surname", CType.string);
tOrder.key("idorder");

let tOrderDetail = d.newTable("orderdetail");
tOrderDetail.setDataColumn("idorder", CType.int);
tOrderDetail.setDataColumn("iddetail", CType.int);
tOrderDetail.setDataColumn("name", CType.string);
tOrderDetail.setDataColumn("surname", CType.string);
tOrderDetail.key("idorder");

d.newRelation("

order_orderdetail", "order", ["idorder"], "orderdetail", ["idorder"]);

Semi-manual creation of a DataSet

It is possible to instantiate a DataSet and then add tables by invoking the createTable() method of a DbDescriptor. This way, the table will automatically have columns, and the primary key set.

Then, add the desired relationships:

let d = new DataSet();
let tOrder = await dbDescriptor.createTable("order");
d.addTable(tOrder);

let tOrderDetail = await dbDescriptor.createTable("orderdetail");
d.addTable(tOrderDetail);

d.newRelation("order_orderdetail", "order", ["idorder"], "orderdetail", ["idorder"]);

Visual creation with the HDSGene tool

It is possible to use a tool, HDSGene, provided by Tempo S.r.l., which integrates with the visual editor of DataSet in Visual Studio. It generates the corresponding JSON in the folder where the DataSet is saved.

Copy the JSON file to the client/datasets folder, assuming the name is dsmeta_order_main.json, and load it with the getDataSet function in the context:

let d = ctx.getDataSet("order", "main");

The convention is that the file name should be dsmeta_[tableName]_[editType].json.

MetaData

The purpose of the MetaData class is to centralize the knowledge of each table in a specific class, which derives from MetaData.

Its use is not specifically required on the backend, but if the frontend myKode_Frontend is used on the client, which might make use of it, and backend services are implemented, they could in turn use the same metadata (instances of MetaData) as the client.

If backend services are implemented that involve creating or manipulating DataSets beyond simple data reading from the database, it is advisable to use the methods of this class.

In summary, each class deriving from MetaData centralizes information about a table, such as:

  • Validity of row data
  • Defaults for field values when a row is created
  • Calculation schema for auto-increment fields (see the PostData class for more information)
  • Structure of lists on that table: which fields should appear, with what label, sorting, etc.

Details can be found in the MetaData file.

Built with Grunt