magic.lambda.sockets 17.2.0

dotnet add package magic.lambda.sockets --version 17.2.0
NuGet\Install-Package magic.lambda.sockets -Version 17.2.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="magic.lambda.sockets" Version="17.2.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add magic.lambda.sockets --version 17.2.0
#r "nuget: magic.lambda.sockets, 17.2.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install magic.lambda.sockets as a Cake Addin
#addin nuget:?package=magic.lambda.sockets&version=17.2.0

// Install magic.lambda.sockets as a Cake Tool
#tool nuget:?package=magic.lambda.sockets&version=17.2.0

magic.lambda.sockets - Using web sockets from Hyperlambda

This project provides web sockets slots for Hyperlambda. The main idea of the project, is that it allows you to resolve Hyperlambda files, execute these, passing in a URL and JSON arguments over a web socket connection - In addition to subscribing to messages published by the server over a web socket connection from some client of your choosing. The project builds upon SignalR, but the internals are completely abstracted away, and you could probably easily exchange SignalR with any other web socket library with similar capabilities. The project contains one socket SignalR hub method with the following signature.

execute(string file, string json);

To connect to the hub use the relative URL /sockets, optionally passing in a JWT token, and then transmit messages to the hub using something such as for instance the following TypeScript.

let builder = new HubConnectionBuilder();

this.connection = builder.withUrl('http://localhost:5000/sockets', {
    accessTokenFactory: () => 'return-your-JWT-token-here'
  }).build();

this.connection.invoke(
  'execute',
  '/foo/some-hyperlambda-file',
  JSON.stringify({
    foo:'bar'
  }));

The above will resolve to a Hyperlambda file expected to exist at /modules/foo/some-hyperlambda-file.socket.hl, passing in the foo argument as lambda nodes.

How to use [sockets.signal]

In addition to the above, you can explicitly publish SignalR events by signaling the [sockets.signal] slot, which will automatically transform the specified children [args] nodes to JSON, and invoke the specified method for all connections somehow subscribing to the specified method - Allowing you to filter according to groups, users and roles if you wish. Below is an example.

sockets.signal:foo.bar
   roles:root, admin
   args
      howdy:world

The above will invoke the foo.bar method, passing in {"howdy":"world"} as a JSON string, but only users belonging to the roles of either admin or root will be notified. Both the [roles] and the [args] arguments are optional. To subscribe to the above invocation, you could use something such as the following in TypeScript.

this.connection.on('foo.bar', (args: string) => {
  console.log(JSON.parse(args));
});

You can also signal a list of specified users, such as the following illustrates.

sockets.signal:foo.bar
   users:user1, user2, user3
   args
      howdy:world

In addition to that you can signal a list of specified groups, such as the following illustrates.

sockets.signal:foo.bar
   groups:group1, group2, group3
   args
      howdy:world

Finally, you can signal a list of specified client connections, such as the following illustrates.

sockets.signal:foo.bar
   clients:e6U2Zz6kqHDCEVyEX6v35w, 5uWWytAM8kJ2gfIL0fEw2A
   args
      howdy:world

The above will only signal the two specified client connections.

Notice - If you signal a group or a list of groups, you'll have to add your users to the group before you do.

Arguments to [sockets.signal]

  • [roles] - Comma separated list of roles to send message to
  • [users] - Comma separated list of users to send message to
  • [clients] - Comma separated list of client connections to send message to
  • [groups] - Comma separated list of groups to send message to
  • [args] - Arguments to transmit to subscribers as JSON (string)

Only one of [users], [roles], [clients], or [groups] can be supplied, and all the above arguments are optional.

Publishing socket messages to groups and users

You can associate a user with one or more groups. This is done with the following slots.

  • [sockets.user.add-to-group] - Adds the specified user to the specified group
  • [sockets.user.remove-from-group] - Removes the specified user from the specified group

Below you can find an example of how to add a user to a group, for then to later de-associate the user with the group.

// Associating a user with a group.
sockets.user.add-to-group:some-username-here
   group:some-group-name-here

// Publishing message, now to group, such that 'some-username-here' gets it
sockets.signal:foo.bar
   group:some-group-name-here
   args
      howdy:world

// De-associating the user with the group again.
sockets.user.remove-from-group:some-username-here
   group:some-group-name-here

Notice - SignalR users might have multiple connections. This implies that once you add a user to a group, all connections are associated with that group. The message will only be published to connections explicitly having registered an interest in the foo.bar message for our above example, irrelevant of whether the user belongs to the group or not.

Sockets meta data

Hyperlambda also allows you to retrieve meta data about currently connected users, through for instance the [sockets.users] slot and the [sockets.users.count] slot, that will return the username of all currently connected users, and the count matching your specified filter condition. An example of using it can be found below.

sockets.users
   filter:some-filter-condition
   offset:3
   limit:20

sockets.users.count
   filter:some-filter-condition

Notice - If a client connected anonymously somehow over a socket, the client will (obviously) not have a username, and the default userId will be returned instead. Also please notice, that each user might have multiple connections, and this will return each connection for each username matching the specified filter condition. The filter conditions and paging arguments are optional, and will be null and 0-10 if not specified.

Sockets connection context

From within your Hyperlambda files executed by invoking the execute method, you have access to your SignalR connectionId as a context object named "sockets.connection". Below is an example of how to retrieve the current SignalR connectionId. Notice, this only works from within a socket executed Hyperlambda file, implying only if you're executing the file using the execute method, through your SignalR socket connection.

get-context:sockets.connection

This might sometimes be useful, especially if you want to dynamically add only one connection to a group for instance. To add the currently active connection explicitly to a group for instance, you can use the following slots.

  • [sockets.connection.enter-group] - Associates the current connection only with the specified group
  • [sockets.connection.leave-group] - De-associates the current connection with the specified group

If the user has additional connections, none of the other connections will be modified in any ways. Also realise that both of these slots can only be used from within a Hyperlambda file executed through a SignalR socket connection somehow. Below is an example.

// Retrieving connectionId
get-context:sockets.connection

// Entering group
sockets.connection.enter-group:x:@get-context
   group:foo-bar-group

// Do stuff here that requires the user to belong to group ...

// Leaving group
sockets.connection.leave-group:x:@get-context
   group:foo-bar-group

Magic's GitHub project page

Magic is 100% Open Source and you can find the primary project GitHub page here.

Project website for magic.lambda.sockets

The source code for this repository can be found at github.com/polterguy/magic.lambda.sockets, and you can provide feedback, provide bug reports, etc at the same place.

  • Build status
  • Quality Gate Status
  • Bugs
  • Code Smells
  • Coverage
  • Duplicated Lines (%)
  • Lines of Code
  • Maintainability Rating
  • Reliability Rating
  • Security Rating
  • Technical Debt
  • Vulnerabilities

The projects is copyright Thomas Hansen 2023 - 2024, and professionally maintained by AINIRO.IO.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on magic.lambda.sockets:

Package Downloads
magic.library

Helper project for Magic to wire up everything easily by simply adding one package, and invoking two simple methods. When using Magic, this is (probably) the only package you should actually add, since this package pulls in everything else you'll need automatically, and wires up everything sanely by default. To use package go to https://polterguy.github.io

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
17.2.0 473 1/22/2024
17.1.7 341 1/12/2024
17.1.6 368 1/11/2024
17.1.5 362 1/5/2024
17.0.1 427 1/1/2024
17.0.0 613 12/14/2023
16.11.5 578 11/12/2023
16.9.0 603 10/9/2023
16.7.0 978 7/11/2023
16.4.1 814 7/2/2023
16.4.0 784 6/22/2023
16.3.1 766 6/7/2023
16.3.0 779 5/28/2023
16.1.9 1,037 4/30/2023
15.10.11 887 4/13/2023
15.9.1 1,020 3/27/2023
15.9.0 869 3/24/2023
15.8.2 930 3/20/2023
15.7.0 837 3/6/2023
15.5.0 1,974 1/28/2023
15.2.0 1,106 1/18/2023
15.1.0 1,545 12/28/2022
14.5.7 1,120 12/13/2022
14.5.5 1,220 12/6/2022
14.5.1 1,093 11/23/2022
14.5.0 1,032 11/18/2022
14.4.5 1,108 10/22/2022
14.4.1 1,185 10/22/2022
14.4.0 1,091 10/17/2022
14.3.1 1,689 9/12/2022
14.3.0 1,061 9/10/2022
14.1.3 1,358 8/7/2022
14.1.2 1,097 8/7/2022
14.1.1 1,086 8/7/2022
14.0.14 1,129 7/26/2022
14.0.12 1,100 7/24/2022
14.0.11 1,095 7/23/2022
14.0.10 1,091 7/23/2022
14.0.9 1,094 7/23/2022
14.0.8 1,156 7/17/2022
14.0.5 1,213 7/11/2022
14.0.4 1,191 7/6/2022
14.0.3 1,148 7/2/2022
14.0.2 1,099 7/2/2022
14.0.0 1,316 6/25/2022
13.4.0 2,499 5/31/2022
13.3.4 1,877 5/9/2022
13.3.1 1,165 5/1/2022
13.3.0 1,140 5/1/2022
13.2.0 1,604 4/21/2022
13.1.0 1,454 4/7/2022
13.0.0 1,146 4/5/2022
11.0.5 1,824 3/2/2022
11.0.4 1,211 2/22/2022
11.0.3 1,209 2/9/2022
11.0.2 1,209 2/6/2022
11.0.1 1,215 2/5/2022
10.0.21 1,200 1/28/2022
10.0.20 1,227 1/27/2022
10.0.19 1,168 1/23/2022
10.0.18 1,149 1/17/2022
10.0.15 1,382 12/31/2021
10.0.14 1,026 12/28/2021
10.0.7 1,881 12/22/2021
10.0.5 1,159 12/18/2021
9.9.9 2,088 11/29/2021
9.9.3 1,363 11/9/2021
9.9.2 1,049 11/4/2021
9.9.0 1,167 10/30/2021
9.8.9 1,135 10/29/2021
9.8.7 1,060 10/27/2021
9.8.6 1,046 10/27/2021
9.8.5 1,161 10/26/2021
9.8.0 1,782 10/20/2021
9.7.9 1,071 10/19/2021
9.7.5 1,900 10/14/2021
9.7.2 835 10/14/2021
9.7.0 1,279 10/9/2021
9.6.6 1,639 8/14/2021
9.2.5 5,533 6/7/2021
9.2.3 1,319 6/6/2021
9.2.2 1,035 6/4/2021
9.2.1 1,180 6/1/2021