Comments (4)
Regarding ^, I've built another example and I'm not seeing the issue anymore. Feel free to ignore!
Would you mind publishing the latest commits to NPM? Thanks in advance 🙂
from ruls.
Done! Published as v1.0.1
from ruls.
Hey, Marcelo!
Thanks for the thorough feedback!
- You have a good point. "less than" is the most commonly used term. I'll send a diff renaming the function (and the related
lowerThanOrEquals
). - I like the idea. Indeed it can be repetitive when there are many signals with the same context. Let me think on where to surface a function like that.
- Rules work just like TypeScript expressions. And the operators that help combine them (
rule.some()
,rule.every()
,rule.none()
) are rules themselves, which makes them nestable. That example you provided works as intended. Or you could also makebetweenSignal
return a rule directly.
const betweenSignal = (min: number, max: number) =>
rule.every([
signals.amountInCents.greaterThanOrEquals(min),
signals.amountInCents.lowerThan(max),
]);
const starbucksRule = rule.every([
betweenSignal(300, 1000),
signals.name.equals("Starbucks"),
]);
- Yeah, I should add an example on how to use async signals in the documentation. The intention is to delay data fetching to when the signal gets evaluated, which helps make the
Context
simpler. That way, some data won't even be fetched depending on how the rule evaluation goes. As an example, we could update your sample code to fetch transaction data from a database like this:
import { rule, signal } from "ruls";
type Transaction = { amountInCents: number; name: string };
type Context = { transactionId: number };
// Here you'd plug a real database
const transactionsDatabase = new Map([
[123, { amountInCents: 500, name: "Starbucks" }],
[246, { amountInCents: 200, name: "Starbucks" }],
]);
async function fetchTransaction(transactionId: number): Promise<Transaction> {
const transaction = transactionsDatabase.get(transactionId);
if (transaction == null) {
throw new Error("Transaction not found");
}
return transaction;
}
const signals = {
amountInCents: signal.number.value<Context>(
async ({ transactionId }) =>
(await fetchTransaction(transactionId)).amountInCents
),
name: signal.string.value<Context>(
async ({ transactionId }) => (await fetchTransaction(transactionId)).name
),
};
// ... same as before
(async () => {
console.log(await isCoffeeTransaction(123)); // true
console.log(await isCoffeeTransaction(246)); // false
})();
(in the process of coming up with this example I found a bug on type checking async signals, which I'll also patch)
Keep the questions coming and I can help make things clearer! I'm also curious on your use case, so we can look for further opportunities to improve the developer experience. Thanks!
from ruls.
That's great André! I'm sure there will be moref feedback, I'll keep them coming 🙂. The idea is awesome, and something that's lacking in the community. I've briefly prototyped ruls
and json-rules-engine
and ruls's API feels so much nicer - great work so far!
My use case is kind of neat. I'm building a personal finance app that enables users to create rules to match their transactions. While I've modeled my own engine at the API level, I also need an interpreter. I could try building my own, but it seems the goals of ruls
are similar to mines (for instance, being fully type safe). For the time being, I'll try building an interpreter around ruls
.
Thanks for the between
idea, love it!
There's one other thing you might be able to help - I'm having a hard time with the encoder. I cannot make the encode
function to pass:
This is the code I'm using
import { rule, signal } from "ruls";
type Context = {
transaction: { amountInCents: number; name: string };
};
const signals = {
amountInCents: signal.number.value<Context>(
(ctx) => ctx.transaction.amountInCents
),
name: signal.string.value<Context>(({ transaction }) => transaction.name),
};
const betweenSignal = (min: number, max: number) =>
rule.every([
signals.amountInCents.greaterThanOrEquals(min),
signals.amountInCents.lowerThan(max),
]);
const starbucksRule = rule.every([
betweenSignal(300, 1000),
signals.name.equals("Starbucks"),
]);
const philzCoffeeRule = rule.every([
betweenSignal(300, 1000),
signals.name.equals("Philz Coffee"),
]);
const ruleDef = rule.some([starbucksRule, philzCoffeeRule]);
/**
* A coffee transaction is a transaction between $3 and $10 at Starbucks or
* Philz Coffee
*/
export const isCoffeeTransaction = async (transaction: {
amountInCents: number;
name: string;
}) => await ruleDef.evaluate({ transaction });
export const encode = () => ruleDef.encode(signals);
I've copied the progammers
example from your docs and it worked. However, I don't understand what am I doing wrong here. Any ideas?
from ruls.
Related Issues (3)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ruls.