New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

lambdaorm

Package Overview
Dependencies
Maintainers
1
Versions
256
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lambdaorm

ORM

  • 0.0.32
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

Lambda ORM

IMPORTANT: the library is in an Alpha version!!!

LambdaORM is an ORM based on using the same syntax of lambda expressions in javascript to write the expressions that will be translated into SQL sentences according to the database. When starting from javascript lambda expressions we can use the IDE's own intellisense to write the sentences.

Queries:

Starting from the entity we have the following methods to assemble the sentences.

OperatorDescriptionSQL Equivalent
filterTo filter the records.WHERE
havingTo filter on groupings.HAVING
mapTo specify the fields to return.SELECT
distinctto specify the fields to return by sending duplicate records.
firstreturns the first recordSELECT + ORDER BY + LIMIT
lastreturns the last recordSELECT + ORDER BY DESC + LIMIT
takereturns one recordSELECT + LIMIT
sortTo specify the order in which the records are returned.ORDER BY
pageTo paginate.LIMIT (MySQL)
includeTo get records of related entities
insertTo insert recordsINSERT
updateTo update records always including a filterUPDATE with WHERE
updateAllto be able to update all the records of an entityUPDATE without WHERE
deleteTo delete records always including a filterDELETE with WHERE
deleteAllTo be able to delete all records of an entityDELETE without WHERE
bulkinsertto insert records in bulkINSERT

There are no methods for the INNER JOIN clause since it is deduced when navigating through the relations of a property.

There are no methods for the GROUP BY clause since this is deduced when grouping methods are used.

Example:

OrderDetails
	.filter(p => p.order.customer.name == customerName)
	.map(p => ({ order: p.order.orderDate, total: sum(p.quantity * p.unitPrice) }))
	.sort(p => desc(p.total))

the previous expression is equivalent to the following statement for MySQL.

SELECT o1.OrderDate AS `order`, SUM(o.Quantity * o.UnitPrice) AS `total` 
FROM `Order Details` o 
INNER JOIN Orders o1 ON o1.OrderID = o.OrderID 
INNER JOIN Customers c ON c.CustomerID = o1.CustomerID 
WHERE c.CompanyName = ? 
GROUP BY o1.OrderDate 
ORDER BY `total` desc 

More info:

  • queries
  • insert
  • update
  • delete
  • bulkinsert
  • include

Includes:

LambdaORM includes the Include method to load related entities, both for OnetoMany, manyToOne and oneToOne relationships.

We can also apply filters or bring us some fields from the related entities.

For each include, a statement is executed bringing all the necessary records, then the objects with relationships are assembled in memory. In this way, multiple executions are avoided, considerably improving performance.

Includes can be used in selects, insert, update, delete, and bulckinsert.

Example:

Orders
	.filter(p => p.id === id)
	.include(p => [p.customer.map(p => ({ name: p.name, address: concat(p.address, ', ', p.city, ' (', p.postalCode, ')  ', p.country) })),
			p.details.include(p => p.product
				.include(p => p.category.map(p => p.name))
			.map(p => p.name))
		.map(p => [p.quantity, p.unitPrice])])
	.map(p => p.orderDate)

The previous sentence will bring us the following result:

[[
{
	"orderDate": "1996-07-03T22:00:00.000Z",
	"customer": { "name": "Vins et alcools Chevalier", "address": "59 rue de l'Abbaye, Reims (51100)  France"
	},
	"details": [
		{
			"quantity": 12, "unitPrice": 14,
			"product": { "name": "Queso Cabrales", 	"category": { "name": "Dairy Products"}
			}
		},
		{
			"quantity": 10, "unitPrice": 9.8,
			"product": { "name": "Singaporean Hokkien Fried Mee",	"category": { "name": "Grains/Cereals" 	}}
		},
		{
			"quantity": 5, "unitPrice": 34.8,
			"product": { "name": "Mozzarella di Giovanni", "category": { "name": "Dairy Products"	}	}
		}
	]
}
]]

More info:

Using the ORM

To work with the orm we do it through a singleton object called "orm".

This object acts as a facade and from this we access all the functionalities.

to execute we have two methods, one lambda to which the expression is passed as a javascript lambda function and another expression to which we pass a string containing the expression.

If we are going to write the expression in the code, we should do it with the lambda function, since this way we will have the help of intellisense and make sure that the expression does not have syntax errors.

But if the expression comes to us from another side, UI, CLI command, persisted, etc, in this case we will use the expression in a string

Example:

import { orm } from 'lambdaorm'

(async () => {
await orm.init()
try {
	//writing the statement as a lambda expression in javascript
	const query = (id: number) => Orders.filter(p => p.id === id).include(p => p.details)
	let result = await orm.lambda(query).execute('source',{ id: 10248 })
	console.log(JSON.stringify(result, null, 2))

	//writing the statement as a lambda expression to a text string
	const expression = 'Orders.filter(p => p.id === id).include(p => p.details)'
	result = await orm.expression(expression).execute('source',{ id: 10248 })
	console.log(JSON.stringify(result, null, 2))

} catch (error) {
	console.log(error)
} finally {
	await orm.end()
}
})()

Class ORM

methodDescription
versionPrints lambdaorm version this project uses.
initGenerates lambdaorm project structure.
modelGenerate model.
syncSyncronize database.
exportExport data from a database
importImport data from file to database
dropRemoves all database objects but not the database.
expressionRun an expression lambda or return information

Transactions

To work with transactions use the orm.transaction method.

This method receives the name of the database as the first argument and as the second it is a callback function that does not pass a Transaction object, in the example we name it tr.

We use the lambda or expression method to execute the sentence (as we found it written).

When we reach the end and return the callback, the orm will internally execute the COMMIT, if there is an exception, internally the ROLLBACK will be executed

Example

import { orm } from 'lambdaorm'

(async () => {

const order={customerId:"VINET",employeeId:5,orderDate:"1996-07-03T22:00:00.000Z",requiredDate:"1996-07-31T22:00:00.000Z",shippedDate:"1996-07-15T22:00:00.000Z",shipViaId:3,freight:32.38,name:"Vins et alcools Chevalier",address:"59 rue de l-Abbaye",city:"Reims",region:null,postalCode:"51100",country:"France",details:[{productId:11,unitPrice:14,quantity:12,discount:!1},{productId:42,unitPrice:9.8,quantity:10,discount:!1},{productId:72,unitPrice:34.8,quantity:5,discount:!1}]};

try {
orm.transaction('source', async (tr) => {
	// create order
	const orderId = await tr.lambda(() => Orders.insert().include(p => p.details), order)
	// get order
	const result = await tr.lambda((id:number) => Orders.filter(p => p.id === id).include(p => p.details), { id: orderId })
	const order2 = result[0]
	// updated order
	order2.address = 'changed 59 rue de l-Abbaye'
	order2.details[0].discount = true
	order2.details[1].unitPrice = 10
	order2.details[2].quantity = 7
	const updateCount = await tr.lambda(() => Orders.update().include(p => p.details), order2)
	console.log(updateCount)
	// get order
	const order3 = await tr.lambda((id:number) => Orders.filter(p => p.id === id).include(p => p.details), { id: orderId })
	console.log(JSON.stringify(order3))
	// delete
	const deleteCount = await tr.lambda(() => Orders.delete().include(p => p.details), order3[0])
	console.log(deleteCount)
	// get order
	const order4 = await tr.lambda((id:number) => Orders.filter(p => p.id === id).include(p => p.details), { id: orderId })
	console.log(JSON.stringify(order4))
})
} catch (error) {
	console.log(error)
}
})()

Operators

The operators used are the same as those of javascript.

below access to their documentation:

Functions

In the case of functions, some correspond to javascript functions and others are specific to sql

below access to their documentation:

Config

Lambda OMR configuration is through a file called lambdaorm.yaml by default it must be in the root of the project.

The file structure is divided into 3 parts.

  • path: paht configuration
  • databases: database configuration
  • schema: schemas configuration (represents the entity model that is mapped with the tables of a database)
path:
  src: path where the project code is located
  data: path where files generated in operations synchronization, export, import, etc. will be stored
databases:
  - name: name with which the database will be identified
    schema: database schema name 
    dialect: [mysql|mariadb|postgres|mssql|oracle|mongo]
    connection: connectionString  | environment variable with the connectionString 
schemas:
  schemaCode:
    name: schema name
    enums: []
    entities:
      - name: name of entity
        mapping: name table on database
        primaryKey: []
        uniqueKey: []
        properties:
          - name: name of property
            mapping: name field on database
            type: [string|boolean|integer|decimal|datetime|date|time]
            nullable: [true|false]
            autoincrement: [true|false]	
				indexes:
          - name: nameOfIndex
            fields: []
				- name: name of relation
            type: [manyToOne|oneTpMany|oneToOne]
            composite: [true|false]	
            from: field From
            entity: name of entity related
            to: field in entity related					

Example:

ath:
  src: src
  data: data
databases:
  - name: mydb
    schema: library
    dialect: mysql
    connection: MY_DB_STRING_CONNECTION
  - name: mysql
    schema: northwind
    dialect: mysql
    connection:
      host: "0.0.0.0"
      port: 3307
      user: test
      password: test
      database: northwind
      multipleStatements: true
      waitForConnections: true
      connectionLimit: 10
      queueLimit: 0
schemas:
  library:
    name: library
    enums:
    entities:
      - name: Reader
        mapping: TB_READERS
        primaryKey: ["id"]
        uniqueKey: ["name"]
        properties:
          - name: id
            mapping: READER_ID
            type: integer
            nullable: false
            autoincrement: true
          - name: name
            mapping: NAME
            nullable: false
            type: string
            length: 80
      - name: Book
        mapping: TB_BOOKS
        primaryKey: ["id"]
        uniqueKey: ["title"]
        properties:
          - name: id
            mapping: BOOK_ID
            type: integer
            length: 14
            nullable: false
            autoincrement: true
          - name: title
            mapping: TITLE
            nullable: false
            type: string
            length: 80
      - name: Loan
        mapping: TB_LOAN
        primaryKey: ["readerId", "bookId"]
        uniqueKey: ["lastName", "firstName"]
        properties:
          - name: readerId
            mapping: READER_ID
            type: integer
            nullable: false
          - name: bookId
            mapping: BOOK_ID
            type: integer
            nullable: false         
        relations:
          - name: reader
            type: oneToMany
            from: readerId
            entity: Reader
            to: id
          - name: book
            type: oneToMany
            from: bookId
            entity: Book
            to: id  

If you want to place the configuration file in another location or with another name, you must pass the path including the name of the configuration file to the method: orm.init(configPath)

Example:

import { orm } from 'lambdaorm'
(async () => {
await orm.init('/home/my/db/book.yaml')
try {
	const result = await orm.expression('Loan.map(p=>{user:p.reader.name,book:p.book.title,date:p.date})').execute('mydb')
	console.log(result)	
} catch (error) {
	console.log(error)
} finally {
	await orm.end()
}
})()

Metadata

Lambda ORM has the following methods to extract metadata information from expressions.

To execute these methods it is not necessary to connect to the database.

methodDescriptionPath
parametersreturns the list of parameters in the expressionorm.lambda(query).parameters(schema)
modelreturns the model of the result in an executionorm.lambda(query).model(schema)
metadatareturns the metadata of the expressionorm.lambda(query).metadata(schema)
sentencereturns the sentence in the specified dialectorm.lambda(query).sentence('mysql','northwind')

Example:

import { orm } from 'lambdaorm'

(async () => {
await orm.init()

try {
	const query = (id:number) => Orders.filter(p => p.id === id).include(p => p.details).map(p => ({ name: p.orderDate, customer: p.customer.name }))

	const parameters = await orm.lambda(query).parameters('northwind')
	const model = await orm.lambda(query).model('northwind')
	const metadata = await orm.lambda(query).metadata('northwind')
	const sql = await orm.lambda(query).sentence('mysql', 'northwind')

	console.log(JSON.stringify(parameters, null, 2))
	console.log(JSON.stringify(model, null, 2))
	console.log(JSON.stringify(metadata))
	console.log(sql)
} catch (error) {
	console.log(error)
} finally {
	await orm.end()
}
})()

Results:

Parameters:

{
  "id": "integer"
}

Model:

{
  "name": "datetime",
  "customer": "string",
  "details": [
    {
      "orderId": "integer",
      "productId": "integer",
      "unitPrice": "decimal",
      "quantity": "decimal",
      "discount": "decimal"
    }
  ]
}

Metadata:

{"n":"select","t":"Sentence","c":[{"n":"filter","t":"Filter","c":[{"n":"===","t":"Operator","c":[{"n":"id","t":"Field","c":[],"e":"Orders","m":"o.OrderID"},{"n":"id","t":"Variable","c":[],"u":1}]}]},{"n":"Orders.o","t":"From","c":[]},{"n":"map","t":"Map","c":[{"n":"obj","t":"Obj","c":[{"n":"name","t":"KeyValue","c":[{"n":"orderDate","t":"Field","c":[],"e":"Orders","m":"o.OrderDate"}]},{"n":"customer","t":"KeyValue","c":[{"n":"name","t":"Field","c":[],"e":"Customers","m":"c.CompanyName"}]},{"n":"__id","t":"KeyValue","c":[{"n":"id","t":"Field","c":[],"e":"Orders","m":"o.OrderID"}]}]}]},{"n":"details","t":"SentenceInclude","c":[{"n":"select","t":"Sentence","c":[{"n":"filter","t":"Filter","c":[{"n":"includes","t":"FunctionRef","c":[{"n":"orderId","t":"Field","c":[],"e":"OrderDetails","m":"o1.OrderID"},{"n":"__parentId","t":"Variable","c":[],"u":1}]}]},{"n":"Order Details.o1","t":"From","c":[]},{"n":"map","t":"Map","c":[{"n":"obj","t":"Obj","c":[{"n":"orderId","t":"KeyValue","c":[{"n":"orderId","t":"Field","c":[],"e":"OrderDetails","m":"o1.OrderID"}]},{"n":"productId","t":"KeyValue","c":[{"n":"productId","t":"Field","c":[],"e":"OrderDetails","m":"o1.ProductID"}]},{"n":"unitPrice","t":"KeyValue","c":[{"n":"unitPrice","t":"Field","c":[],"e":"OrderDetails","m":"o1.UnitPrice"}]},{"n":"quantity","t":"KeyValue","c":[{"n":"quantity","t":"Field","c":[],"e":"OrderDetails","m":"o1.Quantity"}]},{"n":"discount","t":"KeyValue","c":[{"n":"discount","t":"Field","c":[],"e":"OrderDetails","m":"o1.Discount"}]},{"n":"__parentId","t":"KeyValue","c":[{"n":"orderId","t":"Field","c":[],"e":"OrderDetails","m":"o1.OrderID"}]}]}]}],"f":[{"name":"orderId","type":"integer"},{"name":"productId","type":"integer"},{"name":"unitPrice","type":"decimal"},{"name":"quantity","type":"decimal"},{"name":"discount","type":"decimal"},{"name":"__parentId","type":"integer"}],"p":[{"name":"__parentId","type":"array"}],"e":"OrderDetails"}],"r":{"name":"details","type":"manyToOne","composite":true,"from":"id","entity":"OrderDetails","to":"orderId"}},{"n":"Customers.c","t":"Join","c":[{"n":"==","t":"Operator","c":[{"n":"id","t":"Field","c":[],"e":"Customers","m":"c.CustomerID"},{"n":"customerId","t":"Field","c":[],"e":"Orders","m":"o.CustomerID"}]}]}],"f":[{"name":"name","type":"datetime"},{"name":"customer","type":"string"},{"name":"__id","type":"integer"}],"p":[{"name":"id","type":"integer"}],"e":"Orders","a":{"name":"id","mapping":"OrderID","type":"integer","nullable":false,"autoincrement":true}}

Sentence:

SELECT o.OrderDate AS `name`, c.CompanyName AS `customer`, o.OrderID AS `__id` 
FROM Orders o 
INNER JOIN Customers c ON c.CustomerID = o.CustomerID 
WHERE o.OrderID = ? 

SELECT o1.OrderID AS `orderId`, o1.ProductID AS `productId`, o1.UnitPrice AS `unitPrice`, o1.Quantity AS `quantity`, o1.Discount AS `discount`, o1.OrderID AS `__parentId` 
FROM `Order Details` o1  
WHERE  o1.OrderID IN (?) 

Installation

install Lambda ORM

npm install lambdaorm 

And add the packages according to the databases to be used

npm install mysql2 
npm install mariadb
npm install pg # Postgres 
npm install tedious # Microsoft SQL Server
npm install oracledb

to use cli commands install package globally

npm install lambdaorm -g

CLI

CommandDescription
versionPrints lambdaorm version this project uses.
initGenerates lambdaorm project structure.
modelGenerate model.
syncSyncronize database.
exportExport data from a database
importImport data from file to database
dropRemoves all database objects but not the database.
expressionRun an expression lambda or return information

Keywords

FAQs

Package last updated on 09 Oct 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc