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

actml

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

actml - npm Package Compare versions

Comparing version 0.15.1 to 0.15.2

2

package.json
{
"name": "actml",
"version": "0.15.1",
"version": "0.15.2",
"description": "Like jsx but for your business logic",

@@ -5,0 +5,0 @@ "main": "lib",

@@ -1,4 +0,4 @@

# &lt;ActML /> :rocket: <!-- omit in toc -->
![ActML](assets/logo.jpg)
> You know what I really like in React - it teaches you how to build well encapsulated components that are also highly composable. The thing is that React and its JSX is for our UI. It is a view layer that renders stuff on the screen. I want something similar but for my business logic. Something that allows me to use the same patterns but helps me deal with the asynchronous nature of the front-end development. So, I did it. Meet **ActML** - like React but for your business logic.
> You know what I really like in [React](https://reactjs.org/) - it teaches you how to build well encapsulated components that are also highly composable. The thing is that React and its JSX is for our UI. It is a view layer that renders stuff on the screen. I wanted something similar but for my business logic. Something that allows me to use the same patterns but helps me deal with the asynchronous nature of the front-end development. So, I did it. Meet **ActML** - like React but for your business logic.

@@ -8,10 +8,14 @@ - [Concept](#concept)

- [What is an ActML element](#what-is-an-actml-element)
- [Getting in and out of your function/element](#getting-in-and-out-of-your-functionelement)
- [Scope API](#scope-api)
- [Understanding "exports" and "scope" props](#understanding-%22exports%22-and-%22scope%22-props)
- [Understanding "exports" and "scope" props](#understanding-exports-and-scope-props)
- [Catching all the variables](#catching-all-the-variables)
- [More advanced export and import](#more-advanced-export-and-import)
- [Context API](#context-api)
- [Reserved prop names](#reserved-prop-names)
- [The `children` prop](#the-children-prop)
- [The `exports` prop](#the-exports-prop)
- [Dollar sign notation](#dollar-sign-notation)
- [The `scope` prop](#the-scope-prop)
- [Predefined elements](#predefined-elements)
- [Wrapper that scopes everything](#wrapper-that-scopes-everything)
- [`<A>`](#a)
- [Error handling](#error-handling)

@@ -34,24 +38,21 @@ - [Examples](#examples)

What if we have more functions, they depend on each other and some of them are asynchronous:
What if we have more functions, they depend on each other and one of them is asynchronous:
```js
const Greeting = function({ name, children }) {
children(`Hey ${name}!`);
const GetUserFirstName = async function() {
const result = await fetch('https://reqres.in/api/users/2');
return (await result.json()).data.first_name;
};
async function GetProfileName() {
const response = await fetch('https://reqres.in/api/users/2');
const { data: { first_name, last_name } } = await response.json();
return first_name + ' ' + last_name;
}
function Print({ message }) {
const Greeting = function({ name }) {
return `Hello ${name}`;
};
const Print = function({ message }) {
console.log(message);
}
};
run(
<A>
<GetProfileName exports="name" />
<Greeting $name>
{ message => <Print message={message} /> }
</Greeting>
<GetUserFirstName exports="name" />
<Greeting $name exports="message" />
<Print $message />
</A>

@@ -64,10 +65,10 @@ );

1. The `<A>` element is just a wrapper that comes with ActML module.
2. `<GetProfileName>` is an asynchronous function so ActML waits till its promise is resolved. It also returns a result and has `exports` prop defined. That is a special prop which is saying "Export a variable with name `name` and make it available for other elements".
2. `<GetUserFirstName>` is making a request to `https://reqres.in/api/users/2` and gets the first name of the user. It is an asynchronous function so ActML waits till its promise is resolved. When using it we say that it `exports` a variable called `name`.
3. `<Greeting>` needs that `name` variable and uses the special dollar sign notation which to ActML processor means "Inject a variable with name `name` as a prop".
4. `<Greeting>` also has a function as child and it sends its result there which in our case is the full message.
4. `<Greeting>` also formats a message and returns it as a result.
5. `<Print>` just gets the message and prints it out in the console.
_Here is a working [Codesandbox](https://codesandbox.io/s/341xn5vrlq) of the code above._
_Here is a working [Codesandbox](https://codesandbox.io/s/341xn5vrlq) of the code._
So, that is the concept of ActML. It allows us to define in a declarative fashion our business logic. Same as our UI. There is nothing (almost) imperative. In fact all the code that we pass to the `run` function is nothing but definitions of _what_ should happen. It is not saying _how_. This is extremely powerful concept because it shifts the responsibility to another levels and makes the development a lot more easier and predictable. We use composition over raw implementation. If you like this way of thinking then ActML may be your way to deal with asynchronous logic.
So, that is the concept of ActML. It allows us to define in a declarative fashion our business logic. Same as our UI. In fact all the code that we pass to the `run` function is nothing but definitions of _what_ should happen. It is not saying _how_. This is extremely powerful concept because it shifts the imperative code to another level and gives us more options for composition.

@@ -83,3 +84,3 @@ ## What you need to use ActML

The first line is to say to the transpiler that we don't want `React.createElement()` but `A()`. The second line is there because otherwise you'll get `ReferenceError: A is not defined` error. And of course because the `A` function is defining the core unit of ActML - an ActML element.
The first line is to say that we don't want `React.createElement()` but `A()`. The second line is there because otherwise you'll get `ReferenceError: A is not defined` error. And of course because the `A` function is defining the core unit of ActML - an ActML element.

@@ -115,3 +116,3 @@ From a tools perspective you need some sort of [Babel](https://babeljs.io/docs/en/babel-preset-react) integration. There's a React+Redux+ActML example app [here](https://github.com/krasimir/actml/tree/master/examples/react-redux-app) that you can check.

ActML processor assumes that every of the elements is asynchronous. It executes the functions from the outer to inner ones and from top to bottom. All the three types of elements may return another element. In the case of generator we may `yield` also another element. For example:
the ActML processor executes the functions from the outer to inner ones and from top to bottom. All the three types of elements may return another element. In the case of generator we may `yield` also another element. For example:

@@ -143,19 +144,13 @@ ```js

## Getting in and out of your function/element
## Scope API
The input to your ActML element is the attributes that we pass to the tag or if we have to make a parallel with React - the `props`. For example:
The scope API is a mechanism for transferring data between ActML elements.
```js
const Foo = function (props) {
console.log(`Hello ${ props.name }`);
}
### Understanding "exports" and "scope" props
run(<Foo name='John' />); // outputs "Hello John"
```
In React there are couple of approaches to pass data between components. One of them is the [FaCC (function as child component)](https://github.com/krasimir/react-in-patterns/blob/master/book/chapter-4/README.md#function-as-a-children-render-prop) pattern. Let's focus on it and see how it looks like in ActML:
ActML does not process children which are not ActML elements. So, the first possible output is to pass a function as a child and call it via the `children prop. Or the so called [FACC (function as children pattern)](https://github.com/krasimir/react-in-patterns/blob/master/book/chapter-4/README.md#function-as-a-children-render-prop):
```js
const Foo = function ({ name, children }) {
children(`Hello ${ name }`);
children({ message: `Hello ${ name }` });
}

@@ -165,18 +160,12 @@

<Foo name='John'>
{ message => console.log(message) }
{
({ message }) => console.log(message)
}
</Foo>
);
// outputs again "Hello John"
// outputs "Hello John"
```
Another way to pass data between elements is the Scope API.
That's nice but we can't use FaCC everywhere. And we have to do that a lot because that's not React but our business logic. We will probably have dozen of functions that need to communicate between each other. So there is a Scope API that can keep data and share it with other elements. Let's take the following example:
## Scope API
The scope API is a mechanism for transferring data between ActML elements.
### Understanding "exports" and "scope" props
Using the FACC pattern everywhere is not very convenient. So there is a Scope API that can keep data and share it with other elements. Let's take the following example:
```js

@@ -188,8 +177,10 @@ const Foo = () => 'Jon Snow';

<App>
<Foo exports='name'>
<Zoo $name />
</Foo>
<Bar $name />
</App>
run(
<App>
<Foo exports='name'>
<Zoo $name />
</Foo>
<Bar $name />
</App>
);
```

@@ -207,8 +198,10 @@

<App scope='name'>
<Foo exports='name'>
<Zoo $name />
</Foo>
<Bar $name />
</App>
run(
<App scope='name'>
<Foo exports='name'>
<Zoo $name />
</Foo>
<Bar $name />
</App>
);
```

@@ -218,3 +211,3 @@

Another important note here is that once a variable gets caught it doesn't bubble up. So if there are other elements as parents they will not receive it.
Another important note here is that once a variable gets caught it doesn't bubble up. If there are other elements as parents they will not receive it.

@@ -238,3 +231,3 @@ ### Catching all the variables

The `exports` prop may also accept a function. The function receives the result of the function and **must** return an object (key-value pairs). This approach is useful when we want to apply some transformation of the element's result without modifying the actual element. For example:
The `exports` prop may also accept a function. The function receives the result of the element and **must** return an object (key-value pairs). This approach is useful when we want to apply some transformation of the element's result without modifying the actual element. For example:

@@ -282,5 +275,5 @@ ```js

Now when you know about the scope API we could make a parallel with the context API. The scope API is more like a local placeholder of information. While the context API is globally available and it is more about injecting elements.
Now when you know about the scope API we could make a parallel with the context API. The scope API is more like a local placeholder of data. While the context API is globally available and it is more about injecting elements.
The `run` function accepts a second argument which is the initial context. We can pass an object in the format of key-value pairs. For example:
The `run` function accepts a second argument which is the custom context. We can pass an object in the format of key-value pairs. For example:

@@ -331,2 +324,161 @@ ```js

## Reserved prop names
The input to your ActML element is the attributes that we pass to the tag or if we have to make a parallel with React - the `props`. For example:
```js
const Foo = function (props) {
console.log(`Hello ${ props.name }`);
}
run(<Foo name='John' />); // outputs "Hello John"
```
There are couple of prop names that can not be used because they have a special meaning/function.
### The `children` prop
ActML does not process children which are not ActML elements. This means that we may pass just a regular JavaScript function and our ActML will still work. The thing is that this function will not be fired by the ActML processor. We must do that manually by calling the `children` prop:
```js
const Foo = function({ name, children }) {
children({ text: `Hello ${name}` });
};
run(
<Foo name="John">
{
({ text }) => console.log(text)
}
</Foo>
);
// outputs "Hello John"
```
This is actually the so called [FACC (function as children pattern)](https://github.com/krasimir/react-in-patterns/blob/master/book/chapter-4/README.md#function-as-a-children-render-prop) which we know from writing React apps.
The `children` used as a function accepts only an object (key-value pairs). And that's done for a reason. Let's explore the next example:
```js
const Foo = function({ name, children }) {
children({ text: `Hello ${name}` });
};
const Print = function({ text }) {
console.log(text);
};
run(
<Foo name="John">
(<Print $text />)
</Foo>
);
// outputs "Hello John"
```
The result is the same but this time we are using an ActML as a child and not an JSX expression. The argument must be an object because it gets set as a scope of `<Foo>` (read more about the scope API [here](#scope-api)). That's how we may access the `Hello John` via the `$text` prop.
You probably noticed that `<Print>` is wrapped into parentheses. This is to instruct the processor that the element (or elements) must *not* be processed. We will take care by calling `children`. If we forget to add parentheses we will get the following error:
```
You are trying to use "children" prop as a function in <Foo> but it is not.
Did you forget to wrap its children into parentheses.
Like for example <Foo>(<Child />)</Foo>?
```
### The `exports` prop
The `exports` prop defines a new entry in the scope of the element or in some of its parents (read about that in the [scope API section](#scope-api)).
```js
const Foo = function() {
return 42;
}
<Foo exports='answer' />
```
The scope of the `<Foo>` is equal to `{ answer: 42 }`.
We may also pass a function and apply some transformation before storing the data in the scope. The function must return an object (key-value pairs).
```js
const Foo = () => 42;
const Print = ({ bar }) => console.log(bar);
run(
<Foo exports={value => ({ bar: value * 2 })}>
<Print $bar />
</Foo>
);
// outputs: 84
```
### Dollar sign notation
We already saw that on a couple of places. It is basically to say that we want a value which is available in the scope of the parent (or some of its parents) scope.
```js
const Foo = () => 42;
const Print = ({ answer }) => console.log(answer);
run(
<Foo exports="answer">
<Print $answer />
</Foo>
);
// outputs: 42
```
If we don't like the naming we may change it by providing a string as a value. For example:
```js
const Foo = () => 42;
const Print = ({ banana }) => console.log(banana);
run(
<Foo exports="answer">
<Print $answer="banana" />
</Foo>
);
// outputs: 42
```
We may also provide a function and produce whatever new prop (or props) we want:
```js
const Foo = () => 42;
const Print = ({ a, b }) => console.log(`${ a }, ${ b }`);
run(
<Foo exports="answer">
<Print $answer={ value => ({ a: value, b: value * 2 })} />
</Foo>
);
// outputs: 42, 84
```
### The `scope` prop
The `scope` prop is used to catch variables exported by other nested elements. This is to make some data available to a broader portion of the ActML tree.
```js
const Foo = () => 'Jon Snow';
const App = () => {};
const Zoo = ({ name }) => console.log('Zar: ' + name);
const Bar = ({ name }) => console.log('Bar: ' + name);
run(
<App scope='name'>
<Foo exports='name'>
<Zoo $name />
</Foo>
<Bar $name />
</App>
);
```
Normally `$name` is not available for `<Bar>` because it is exported by a sibling `<Foo>`. However `<App>` is catching it and it makes it available for `<Bar>`.
The `scope` prop accepts a single name or comma separated list. It also accepts `*` as a value which means catch everything. The build-in `<A>` element has this by default.
## Predefined elements

@@ -336,3 +488,3 @@

### Wrapper that scopes everything
### `<A>`

@@ -339,0 +491,0 @@ The `<A>` element has the ability to scope everything. So if you need that functionality and you a wrapper this is a good element to use.

Sorry, the diff of this file is not supported yet

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