open-index/open-npm huggingface dataset:
npm package: @htblaleonie/core
Description: Leonie Core
Author: Stefnotch
Latest version: 0.0.3

# Leonie Core

The Leonie core library. It has a type safe API for sending and receiving Leonie-approved MQTT messages.

This library is intended for Node.js and modern browsers!
Also note that every file import must have a `.js` at the end because of [this Typescript bug](https://github.com/microsoft/TypeScript/issues/16577)

## Usage

Simply create a new Leonie client and subscribe to the events that interest you.
```typescript
import { LeonieClient } from "@htblaleonie/core";

const leonieClient = new LeonieClient(config.mqttUrl, "debug-token");
leonieClient.action.animation.subscribe((topic, payload, error) => {
  if(!error) {
    console.log("Received " + payload);
  }
});

leonieClient.action.animation.publish({ animation: "dance" });
```

It is also possible to directly use the MQTT client.
```typescript
import { MqttClient } from "@htblaleonie/core";

const mqttClient = new MqttClient(config.mqttUrl);
mqttClient.subscribe("debug-token/action/animation", (topic, payload, error) => {
  if(!error) {
    console.log("Received " + payload);
  }
});

mqttClient.publish("debug-token/action/animation", { animation: "dance" });
```

## Building and publishing

To easily make this code available to other teams, it's being published on `npm`. Effectively, this means that everything in this folder is public!

To publish a new version on `npm`

1. Increment the version in the `package.json`
2. Run `npm run build`
3. Run `npm publish`

## Recursive Types Demo

The `leonie-client.ts` makes use of this sort of arcane magic.

I recommend copying this into a `.ts` file in VSCode.
The relevant Typescript concepts are mapped types, [conditional types](https://artsy.github.io/blog/2018/11/21/conditional-types-in-typescript/) and recursive types.

```typescript
// Test type
type test = {
  cat: "meow";
  nested: {
    snake: "ssss";
    supernested: {
      cow: "mooo";
    };
  };
};

// Flat copy
type FlatCopy<T> = {
  [key in keyof T]: T[key];
};

let flatResult: FlatCopy<test> = undefined as any;
// Hover over the different parts
flatResult.nested.supernested.cow;

// Deep copy (recursive)
type Copy<T> = {
  [key in keyof T]: Copy<T[key]>;
};

let result: Copy<test> = undefined as any;
// Hover over the different parts. Note how they're Copy<{...}>
result.nested.supernested.cow;

// Flat copy and modify
type FlatCopyAndReplace<T> = {
  [key in keyof T]: T[key] extends string ? number : T[key];
};

let flatResultAndReplace: FlatCopyAndReplace<test> = undefined as any;
flatResultAndReplace.cat;
flatResultAndReplace.nested.snake;

// Deep copy and modify
type CopyAndReplace<T> = {
  [key in keyof T]: T[key] extends string ? number : CopyAndReplace<T[key]>;
};

let resultAndReplace: CopyAndReplace<test> = undefined as any;
resultAndReplace.nested.supernested.cow;
resultAndReplace.nested.snake;
```