npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@plurid/bluefig-server

v0.0.0-4

Published

Bluefig Server for Device Configuration

Downloads

8

Readme

bluefig is intended for the configuration of devices without input/output mechanisms.

The bluefig-server runs on the device and the user connects to it through the bluefig-client, running on a common user terminal.

The user then interacts with the bluefig-client, effectively changing the internal state of the bluefig-server machine, within the limits of the views (elements and actions) specified by the bluefig-server.

Contents

Usage

The bluefig-server will load at start a list of views and hooks which will determine the bluefig-client user interface and the bluefig-server behavior.

A bluefig view is comprised of elements and actions.

The elements will be sent by the bluefig-server to be rendered by the bluefig-client.

The elements used for input (input-x, button) can have an action field. When the user interacts with the element on the bluefig-client, the established action will run accordingly on the bluefig-server.

An action is an async function which can return another view; either one already defined in the views object, or something dynamically computed based on the functions payload, the object containing all the arguments passed from the store.

Any action will also have as the second argument a notify function which will push a notification to the bluefig-client, and as the third argument an event function which can be used to trigger a bluefig-server event, such as set-token to set the access token.

Example

Considering the simple view

import {
    ViewsServer,
} from '@plurid/bluefig-server';


const views: ViewsServer = {
    '/': {
        title: 'Index View',
        elements: [
            {
                type: 'text',
                value: 'this is a simple view',
            },
            {
                type: 'input-text',
                title: 'Input Text',
                store: 'inputTextStore',
            },
            {
                type: 'button',
                title: 'Click Me',
                action: 'clickAction',
            },
        ],
        actions: {
            'clickAction': {
                arguments: [
                    'inputTextStore',
                ],
                execution: async (
                    payload,
                ) => {
                    console.log('Click action called', payload.inputTextStore);
                },
            },
        },
    },
};

the bluefig-client will then render an interface with a text input field which will listen for changes and store the content in a variable named inputTextStore which can then be passed to the action clickAction, triggerable by clicking on the button.

The bluefig-server will output at click

> Click action called input text

Configuration

The bluefig-server will by default load the views and hooks from ~/.bluefig.

Custom views and hooks paths can be provided using the environment variables BLUEFIG_VIEWS_PATH and BLUEFIG_HOOKS_PATH.

The environment variable BLUEFIG_SERVICE_NAME can be used to set the name appearing in the bluefig-client scan list.

Use Cases

bluefig can be used to:

  • connect a device to Wi-Fi, by selecting from a bluefig-server provided list and entering the passkey;
  • set an administrator password on the device;
  • reset device to factory settings;
  • abstract the execution of complex logic, e.g. starting/stopping a process line with one button;
  • read/export device analytics;
  • read/write custom configuration files†;
  • execute custom shell commands†;

† In order to ensure the device security, the interaction with configuration files/shell commands should be done indirectly, the bluefig-server exposing only a limited interaction mode to the bluefig-client.

In Use

bluefig is used to configure:

  • deserver: admin setup, user generation, Wi-Fi selection, disk formatting, docker/processes lifecycle (setup-stop-restart).

Elements

The elements of a view are comprised of ViewElements.

export type ViewElement =
    | ViewText
    | ViewInputText
    | ViewInputSelect
    | ViewInputSwitch
    | ViewInputSlider
    | ViewButton
    | ViewImage
    | ViewFile
    | ViewDivider
    | ViewList;

Any field of an element, except the type, can receive a static value (string, boolean, etc.), or an async function which will be evaluated at view-request time.

Helper types

export type PromiseOf<T> = () => Promise<T>;
export type TypeOrPromiseOf<T> = T | PromiseOf<T>;

export type StringOrPromiseOf = TypeOrPromiseOf<string>;
export type StringArrayOrPromiseOf = TypeOrPromiseOf<string[]>;
export type NumberOrPromiseOf = TypeOrPromiseOf<number>;
export type BooleanOrPromiseOf = TypeOrPromiseOf<boolean>;
export type StringOrNumberOrPromiseOf = TypeOrPromiseOf<string | number>;
export type StringOrNumberOrStringNumberArrayOrPromiseOf = TypeOrPromiseOf<string | number | (string | number)[]>;
export type ViewElementsOrPromiseOf = TypeOrPromiseOf<ViewElement[]>;

text

export interface ViewText {
    type: 'text';
    value: StringOrPromiseOf;
    selectable?: BooleanOrPromiseOf;
}
// tests/example.all.js
    '/text': {
        title: 'text',
        elements: [
            {
                type: 'text',
                value: 'Text',
            },
        ],
    },

input-text

export interface ViewInputText {
    type: 'input-text';
    title?: StringOrPromiseOf;
    store: StringOrPromiseOf;
    initial?: StringOrPromiseOf;
    secure?: BooleanOrPromiseOf;
}
// tests/example.all.js
    '/input-text': {
        title: 'input text',
        elements: [
            {
                type: 'input-text',
                title: 'Input Text',
                store: 'inputText',
            },
        ],
    },

input-select

export interface ViewInputSelect {
    type: 'input-select';
    title?: StringOrPromiseOf;
    /**
     * Select from the options list.
     */
    options: StringArrayOrPromiseOf;
    store: StringOrPromiseOf;
    initial?: StringOrNumberOrStringNumberArrayOrPromiseOf;
    /**
     * Allow for multiple selection.
     */
    multiple?: BooleanOrPromiseOf;
    /**
     * Set initial value, index of `options`.
     */
    action?: StringOrPromiseOf;
}
// tests/example.all.js
    '/input-select': {
        title: 'input select',
        elements: [
            {
                type: 'input-select',
                title: 'Input Select',
                store: 'inputSelect',
                options: [
                    'one',
                    'two',
                    'three',
                ],
                initial: 1,
            },
        ],
    },

input-switch

export interface ViewInputSwitch {
    type: 'input-switch';
    title: StringOrPromiseOf;
    store: StringOrPromiseOf;
    initial?: BooleanOrPromiseOf;
    action?: StringOrPromiseOf;
}
// tests/example.all.js
    '/input-switch': {
        title: 'input switch',
        elements: [
            {
                type: 'input-switch',
                title: 'Input Switch',
                store: 'inputSwitch',
            },
        ],
    },

input-slider

export interface ViewInputSlider {
    type: 'input-slider';
    title: StringOrPromiseOf;
    store: StringOrPromiseOf;
    initial?: NumberOrPromiseOf;
    action?: StringOrPromiseOf;
    maximum?: NumberOrPromiseOf;
    minimum?: NumberOrPromiseOf;
    step?: NumberOrPromiseOf;
}
// tests/example.all.js
    '/input-slider': {
        title: 'input slider',
        elements: [
            {
                type: 'input-slider',
                title: 'Input Slider',
                store: 'inputSlider',
            },
        ],
    },

button

export interface ViewButton {
    type: 'button';
    title: StringOrPromiseOf;
    action: StringOrPromiseOf;
}
// tests/example.all.js
    '/button': {
        title: 'button',
        elements: [
            {
                type: 'button',
                title: 'Button',
                action: 'actionButton',
            },
        ],
    },

image

export type ViewImageAlignment = 'left' | 'right' | 'center';

export interface ViewImage {
    type: 'image';
    source: StringOrPromiseOf;
    contentType?: StringOrPromiseOf;
    height?: NumberOrPromiseOf;
    width?: NumberOrPromiseOf;
    alignment?: ViewImageAlignment | PromiseOf<ViewImageAlignment>;
}
// tests/example.all.js
    '/image': {
        title: 'image',
        elements: [
            {
                type: 'image',
                source: 'bluefig-logo-128x128.jpg',
            },
        ],
    },

file

export interface ViewFile {
    type: 'file';
    title: StringOrPromiseOf;
    source: StringOrPromiseOf;
    contentType?: StringOrPromiseOf;
}
// tests/example.all.js
    '/file': {
        title: 'file',
        elements: [
            {
                type: 'file',
                title: 'Sample File.png',
                source: 'a-file.txt',
            },
        ],
    },

divider

export interface ViewDivider {
    type: 'divider';
}
// tests/example.all.js
    '/divider': {
        title: 'divider',
        elements: [
            {
                type: 'divider',
            },
        ],
    },

list

export interface ViewList {
    type: 'list';
    items: ViewElementsOrPromiseOf;
}
// tests/example.all.js
    '/list': {
        title: 'list',
        elements: [
            {
                type: 'list',
                items: [
                    {
                        type: 'text',
                        value: 'Text In List',
                    },
                    {
                        type: 'input-text',
                        title: 'Input Text In List',
                        store: 'inputTextInList',
                    },
                ],
            },
        ],
    },

Packages

@plurid/bluefig-server • server

Codeophon