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

@jatahworx/bhive-toolkits

v9.2.3

Published

Palette toolkits

Downloads

198

Readme

bhive-toolkits

Service Designer

Creating A Node

View

Using GADBAD (Generating Attributes Dom Based on Attribute Def)

This will take care of DOM creation and form validation for the defaults

  • Define the attrDef object for each of the defaults object preperty in the ${nodename}.HTML file.

    Properties of attrDef object

    • attrType: type of the field (each value corresponds to a Jquery widget)
      values can be: 'INPUT' | 'TOGGLE_BUTTON' | 'SELECT' | 'TYPED_INPUT'
    • label: Label text to be used for that field
    • options: options object expected by the each type of widget (documented below under each widget)

Example:
TestNode.html (Refer "nodeDef" topic under Registering NodeType for ht other nodeDef properties' description)

<script type="text/x-red" data-template-name="TestNode"></script>
<script type="text/javascript">
    registerNode({
        nodeType: 'TestNode',
        nodeDef: {
            color: "black",
            defaults: {
                testdata: {
                    value: 'Default test data; Changes should reflect back;',
                    attrDef: { attrType: 'INPUT', options: { placeholder: 'testdata', required: true  } }
                },
                thisisthenewdefault: {
                    value: 'test you',
                    attrDef: { attrType: 'INPUT', options: { placeholder: 'thisisthenewdefault' } }
                },
                anothernewdefault: {
                    value: 'another test you',
                    attrDef: { attrType: 'INPUT', options: { placeholder: 'anothernewdefault' } }
                },
                testinganotherone: {
                    value: 'testinganotherone',
                    attrDef: { attrType: 'INPUT', options: { placeholder: 'testinganotherone' } }
                },
                amqpConfig: {
                    type: 'amqp-config', value: {}, required: true, options: {},
                    attrDef: { label: 'AMQP Config' }
                },
                checkbox: {
                    value: false,
                    attrDef: {attrType: 'TOGGLE_BUTTON', options: {label: 'A togglebutton'}}
                }
            },
            .
            .
            .
            // Other properties
        }
    });
</script>

NOTE
Limitations:

  • Editable list is not yet implemented
  • switching between fields is not current supported in this. It has to be manually
    implemented in "oneditprepare" hook

Codegen

Registering NodeType

  • nodeType

  • serviceType: ("client"|"server")

  • nodeDef: All the function properties' "this" will refer to the current node.

    • defaults: (object) the editable properties for the node. Each property in "defaults" is an object and can have following properties

      • value: initial value for the property
      • validate(Regex | function(v, ServiceDesigner)) => boolean: This is used for validation of the property after a node is added to the canvas and after the node is edited. It should return true or false
      • required(boolean): If the field is required fr he node to be valid.
      • Example for "defaults" object: (Snippet from the "HttpOut" server node)
      defaults: {
        // input text fields
        name: { value: '' },
        // headers
        headers: {
            value: {
                type: 'bh.input',
                value: ''
            }
        },
        // response body
        responseBody: {
            value: {
                type: 'bh.input',
                value: ''
            },
            validate: function (v) {
                return this.responseType === 'next' || server.validators.patterns.noblank.test(v.value);
            }
        },
        httpcode: { value: '', validate: function (v) { return this.responseType === 'next' || server.validators.patterns.noblank.test(v) } },
        responseType: { value: '', required: true },
        responseMapping: { value: '', },
        cookies: { value: [] },
        // ports
        inputs: { value: 1 },
        outputs: { value: 0 },
        editableListData: {
            value: {
                headers: [],
            }
        },
        cookiesList: {
            value: {}
        },
        switchStates: {
            value: {
                headers: 'Map',
                cookies: 'Map'
            }
        }
    • inputs: (number) how many inputs the node has, either 0 or 1.

    • outputs: (number) how many outputs the node has. Can be 0 or more.

    • color: (string) the background colour to use.

    • paletteLabel: (string|function) the label to use in the palette.

    • label: (string|function) the label to use in the workspace.

    • labelStyle: (string|function) the style to apply to the label.

    • inputLabels: (string|function) optional label to add on hover to the input port of a node.

    • outputLabels: (string|function) optional labels to add on hover to the output ports of a node.

    • icon: (string) the icon to use.

    • oneditinit: (function) Event that opens the Edit dialog box, which can be used to initialize the input widgets on any of the DOM elements.

      Note: node-input-{defaultProperty}, node-input-typed-{defaultProperty} values will get auto-initialized back to the respective input fields throughout this cycle.

    Example:

    <input id="node-input-name" placeholder="Name" />
    ...
    <input id="node-input-typed-logObject" />
    <!-- 'logObject' in id of the input tag matches the default property 'logObject' in the node (ref. to Comment-A) -->
    ...
    registerNode({
      nodeType: 'Log',
      serviceType: 'client',
      nodeDef: {
        ...
        ...
        defaults: {
          ...
          name: {value: ''},
          logObject: {value: 'bh.input'},  // Comment-A
          ...
        },
        oneditinit: function(ServiceDesigner) {
          ...
          ...
          $('node-input-name').inputField();
          $('node-input-typed-logObject').typedInput({
            types: [
              ...
            ],
            change: validateForm
          })
        }
      }
    })
    • initdefaults ((SRD: ServiceDesignerObject) => this:DEFAULTS): this in initdefaults context refers to the defaults Object of the current node. Repopulate/change the defaults Object and return for changing the defaults object dynamically. The first argument is the node object and second is the SRD object. Only works for Editing node, not for config node as the issue for dynamic defaults update only exists there.

    • oneditinit ((SRD: ServiceDesignerObject) => void): Called before oneditprepare. To be used to attach dynamic UI widgets.

    • oneditprepare (function(SD) => void): Event that can be used to pick-up the reinitialized values to further do any other operations

    • onpropertiesvalidated (function(SD) => void): Event called after default required fields are validated

    • oneditsave (function(SD) => void): called when the edit dialog is okayed.

    • oneditcancel (function(SD) => void): called when the edit dialog is cancelled.

    • oneditresize (function(SD) => void): called when the edit dialog is resized.

    • afteradd (function(SD) => void): Called after a node is added to the set of nodes in the service-designer services.

    • onpropertieschange (function(oldPropertyValues, ServiceDesigner)): called after node properties are changed, just after "oneditsave" or when "undo" is performed.

    • afterservicerename (function(ServiceDesigner)): called after the node's service is renamed.

    • shape 'circle' for start type nodes or leave blank for the default 'square'.

    • docsLink (string | funciton(serviceDesignerType: "client" | "server"): {nodePath: string} | {fullPath: string})

      Example:

      // As a string
      docsLink: 'start-node'
      
      // As a function #1 - that returns only the nodepath
      
      docsLink: function(serviceDesignerType) {
        return {
          nodePath: 'start-' + serviceDesignerType + '-node';
        }
      }
      
      // As a function #2 - that returns the entire url
      
      docsLink: function(serviceDesignerType) {
        return {
          fullPath: 'docs.official.website/node-docs/' +  serviceDesignerType + '/start-node';
        }
      }
    • category (string): the palette category the node appears in

Styling Node Attribute Window

  • Create a class for the node under 'bhive-ad/src/scss/nodes' folder
  • SCSS classes should be nested under the attribute selector - [servicetype][editing-node-type="NodeType"] Example: If the nodeType is "HttpRequest" and the servicetype is "server", then the class structure of the "httprequest.scss" file would be,
// This prevents your node style bleeding into other DOM elements.
[server][editing-node-type='HttpRequest'] {
    .node-input-field {
        width: 100%;
    }
    input[type='text']:focus {
        background: gray;
    }
}
  • Finally, import the style in styles.scss

Node Dev Utils

  • SwitchFields (util.service.ts>switchFields()) : Use this function to toggle 2 fields with a switch(button). Current state can also be retrieved which might be used for displaying the correct field when openeing the editor window.

  • ServiceDesigner.utils.isValidHttpStatusCode(httpStatusCode);: Returns boolean. Validates against a list of http status codes.

  • A node user can create assignment complex object by creating:

    <input id="node-input-a.b.c" />
    defaults: {
        // you will have to provide two defaults
        // one with the mapping
        'a.b.c': { value: '' },
        // one as a default
        a: {value: ''}
      }

    the node will auto populate default property 'a' with whatever value is assigned to 'node-input-a.b.c', and generate a object:

    a: {
      b: {
        c: ''
      }
    }

JQuery Widgets

[1. inputField widget]

options

HTML attrs acknowledged by this widget
  • placeholder: Can be a string or "[i18nPrefix]path"
  • required

Example

<!-- <placeholder form i18n> -->
<input
    type="text"
    id="cookies-name"
    placeholder="[n-sd]common.label.name"
    required
/>

OR

<!-- <plaintext placeholder> -->
<input type="text" id="cookies-name" placeholder="Name" required />

properties:

  • wrapperClass:(string) - Add classes to the wrapper div separated by space.
  • wrapperAttr:({ [key: string]: any }) - Append attributes to wrapper div. JQuery PlainObject with keys(attr name) and values(attr value)
  • inputClassList?:(string) - Space seperated classes.
  • placeholderClassList?:(string) - Space seperated classes.
  • placeholder?:(string) - Text to show as input field's placeholder.
  • attrs?: ({ [key: string]: any }) - JQuery PlainObject with keys(attr name) and values(attr value).
  • props?: ({ [key: string]: any }) - JQuery PlainObject with keys(prop name) and values(true/ false).
  • value?:(string) - default value for the inputField.
  • validateOnCreate?:(boolean) - Wheather validation should run as soon as the widget gets created.
  • validatorRegexp?: RegExp; - Regex to validate the input value against.
  • errorText?:(string) - Custom error message when the input value fails the test against pattern.
  • errorClassList?:(string) - Space seperated classes,
  • required?: (boolean) - true if the inputField is required.
  • disabled: (boolean)

Dynamically Updatable Options

  • placeholder

  • attrs

  • wrapperAttr

    Example

    // updating "placeholder" after initialization
    $('#node-input-name').inputField('option', { placeholder: 'asdasdas' });

Functions:

  • validator: (inputValue: string) => {valid: boolean, errorMessage: string} - Function called on 'input' event to the inputElement. It should return validity and associated errorMessage (if invalid).
  • updations: (elmData: any, inputValue: string) => any - Miscellaneous updates. Called after the input value validation.
  • onError: Function that should be executed if the inputfield value becomes invalid(function).

Public methods:

  • show: displays the widget
  • hide: hides the widget
  • toggle: hides if displayed. else, displays.
  • reset: clears the value and clears the data associated with the inputField.
  • valid: get the validity of the inputField.
  • value(v): Use this to correctly set the value. If 'v' is empty, it returns the current value.

Usage Example:

$('#node-input-name').inputField({
    validator: function (v) {
        let valid = true;
        let msg = '';
        if (!SD.validators.patterns.validbh.test(v)) {
            valid = false;
            msg = 'Name should contain alphanumeric chars';
        } else if (
            SD.nodes
                .workspaceNodes(node.type, node.id, 'name', node.z)
                .nodePropsArr.includes(v)
        ) {
            valid = false;
            msg =
                'Middlewarestart node with the same name exists in this workspace';
        }
        return {
            valid: valid,
            errorMessage: msg,
        };
    },
    validateOnCreate: true,
    disableDoneIfInvalid: true,
    enableDoneIfValid: true,
});

2. selectField widget

Provide a JSON object of the format shown below:

Properties

<select id="node-input-selectFieldname"></select>

To give tooltip for the option, define a property "description".

Example:

{value: 'application/json', displayValue: 'JSON', description: "Select this if the server sends json data"}

optionsgroupData example:

$('#node-input-selectFieldname').selectField({
    optionsgroupData: [
        {
            'group 1': [
                { id: 'opt1', name: 'option1' },
                { id: 'opt2', name: 'option2' },
            ],
            'group 2': [
                { id: 'opt3', name: 'option2' },
                { id: 'opt4', name: 'option3' },
                { id: 'opt5', name: 'option4' },
            ],
        },
    ],
    value: node.encoding,
    change: val => {
        validateForm();
    },
});

3. toggleButton widget

options

Properties

  • cssObject: Jquery cssObject - It will be applied on the outermost element of the toggleGroup.
  • label: string - Label for the button toggle.
  • labelCss: Jquery cssObject for styling the togglebuttn label.
  • states: {on: string, off: string} - Name for the 'on' and 'off' states.
  • labelId: string - Id applied for the label
  • inputId: string - Id applied to the input and used in the label for attributes and it will treated like clicking on the associated input element
  • containerId - string: adds th id to the container of the toggle button

Functions

  • afterToggle: (checked: boolean) => any - Executed after the button has been toggled (either on or off). ​

Public Methods

  • toggleOn: toggle on the button.
  • toggleOff: toggle off the button.
  • state: Get the assciated state of the current button position. If no state option was provided, returns true or false

Usage Example:

<input type="checkbox" id="node-input-useProxyAuth" />
$('#node-input-useProxyAuth').toggleButton({
    label: SRD._('httpProxy.label.useProxyAuth'),
    labelCss: {
        'margin-right': '3em',
    },
    cssObject: {
        'margin-top': '1.5em',
    },
    // Provide state
    states: {
        on: 'use',
        off: 'donotuse',
    },
    afterToggle: updateProxyAuth,
});

// Get the current state
const state = $('#node-input-useProxyAuth').toggleButton('state');
// "state" now contains 'use' or 'donotuse' string as per the 'states' options object

4. editableList widget

Official Docs: https://nodered.org/docs/api/ui/editableList/

options

Properties:

  • addButton : boolean|string - text for add label, default 'add'
  • height : number|'auto'
  • sortable : boolean|string - string is the css selector for handle
  • connectWith : css selector of other sortables
  • removable : boolean - whether to display delete button on items
  • scrollOnAdd : boolean - whether to scroll to newly added items
  • showAddBtnLabel: boolean - Whether to show the addButton label as its buttonName.

Functions

  • resizeItem : function(item) - called to resize individual item
  • sortItems : function(items) - when order of items changes
  • resize : function - called when list as a whole is resized
  • addItem : function(row,index,itemData) - when an item is added
  • removeItem : function(itemData) - called when an item is removed
  • filter : function(itemData) - called for each item to determine if it should be shown
  • sort : function(itemDataA,itemDataB) - called to sort items
  • validator: function - called before adding an item to the edtableist. If "false", it is skipped.

Public methods

  • addItem(itemData)
  • removeItem(itemData)
  • width(width)
  • height(height)
  • items()
  • empty()
  • filter(filter)
  • sort(sort)
  • length()
  • checkUnique(editableListDataArray)

5. typedInput widget

Official Docs: https://nodered.org/docs/api/ui/typedInput/

options

Properties:

Functions

Public methods

CSS classes for alignemtments

  • editor-form-row - Should be applied to immediate parent element if there is no error message

  • editor-form-row-error-msg - Should be applied to immediate parent element if there is error message

  • editor-form-row-label - Should be applied to every label

  • editor-form-row-with-sub-ele - Sholud be applied to immediate parent element if there are any sub elements are present

  • editor-form-row-sub-ele - Should be applied if the element is sub element

Node Codegen

  • Methods

    • generateImports(): Should return an array of library, modules and alias.
    /**
     * @param {{depth: number, pathToUtilsRoot: string, pathToServiceRoot: string}} rootPaths
     * @returns {{
       *  library: string,
       *  modules?: [string],
     *  alias?: string,
     *  default? string,
       * }[]} imports
       */
      generateImports(rootPaths) {
          return [
              {
                  library: 'express-session',
                  alias: 'expressSession',
              },
              {
                  library: '../helper/generic/SessionStore',
                  modules: [
                      'TypeormStore'
                  ]
              },
              {
                  library: 'typeorm',
                  modules: [
                      'getConnection'
                  ]
              }
          ]
      }
    • generateSnippet(): Should return a string which will be generated in the placeholder of the node.

    • updateTemplate(serviceClassTemplate): This callback gets the whole service file as string. Manipulate anything and return the file string back for codegen.

    • getErrorTemplate(): A template to validate your generated code against. Default:

    getErrorTemplate() {
            return `
            export class errorCheck {
                    //appendnew_node
            }
            `;
        }
  • getCallTemplate(): If your snippet is a function then, it will need a call template.

    getCallTemplate() {
          return "bh = await this." + this.functionName + "(bh);"
      }
  • Method Variables:

    • this.viewType: Name of the supported views.

      // supported types
      {
          COMMON: 'common',
          SERVER: 'server',
          CLIENT: 'client',
          MIDDLEWARE: 'middleware'
      }
      
      // Usage:
      this.viewType = BaseComponent.viewTypes.SERVER;
    • this.nodeType: Name of the supported node type.

      START: 'start', MIDDLEWARE: 'middleware'

      
      }
      
      // Usage: this.nodeType = BaseComponent.nodeTypes.MIDDLEWARE;

Generic style class

  • The generic-style.scss file contains the trivial css stylings that can be included for the node template custom styling.
  • We can also specify the custom CSS class in the generic-style.scss class which is located in 'src/scss' folder. ```css .padding-left-0 { padding-left: 0 !important; }

.padding-right-0 { padding-right: 0 !important; }

.padding-top-0 { padding-top: 0 !important; }

.padding-bottom-0 { padding-bottom: 0 !important; }

.margin-left-0 { margin-left: 0 !important; }

.margin-right-0 { margin-right: 0 !important; }

.margin-top-0 { margin-top: 0 !important; }

.margin-bottom-0 { margin-bottom: 0 !important; }

.margin-top-1 { margin-top: 1 !important; }

.margin-bottom-1 { margin-bottom: 1em !important; }

.width-100 { width: 100% !important; }

.height-100 { height: 100% !important; }

.diplay-block { display: block !important; }

.display-flex { display: flex !important; }

.vertical-align-top { vertical-align: top !important; }

## Componets Development

### Attribute View Types

- AUTOCOMPLETE
  * Example attribute definition using "AUTOCOMPLETE" type:
  ```javascript
  let anAttributesInstance = null;
  module.exports = class AnAttribute {
      constructor() {
          if (!anAttributesInstance) {
              anAttributesInstance = this;
              this.displayAs = 'anAttr';
              this.value = '[anAttr]';
              this.type = 'AUTOCOMPLETE';
           /*
            * Note: "this.values" type is "Array<string> | Array<{value: any, display: string}>"
            * and, "display" field should have the name of one of the fields in "value" property
            * if the type is Array<{value: any, display: string}>.
            */
              this.values = [
                  { display: "Left", value: { a: 'adasd', Left: 'asdasd' } },
                  { display: "Center", value: { l: "center", Center: "000" } },
                  { display: "FuckThis", value: { k: "justify", FuckThis: "Yes" } }
              ];
          }
          return fxShowInstance;
      }
  }
  • DROPDOWN
  • TOGGLE
  • LIST_DIALOG