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

weblang

v0.14.1

Published

Weblang low code programming language

Downloads

27

Readme

Weblang

The Weblang low code programming language lets you write safe, portable and efficient code with minimal logic. Created to let users run code on your server, but can be extended to run anything anywhere.

Features

  • Extendable dynamic runtime
  • Written in Javascript, can run anywhere
  • Easy to learn, very minimal logic
  • Safe and secure
    • File and network access prohibited by default
    • Allows running of user defined code on your server
  • JSON compatible
    • Write code using YAML syntax
    • Easily transform to and from JSON

Ready to try it out?

Install

npm i weblang

Usage

let weblang = require('weblang')
let code = '=hello: world'
let state = await weblang.init().run(code)

How it works

Generally, setting a variable starts with =, variable lookup starts with $, and functions start with @.

Variables have dynamic types, just as with YAML. All variables are global, there is no scope, not even inside if and else blocks.

Functions are added through extensions. Even the core functionality can be overridden, Weblang is meant to be extended.

Set and Get variables

Variables are stored in state.vars:

  • Setting a variable starts with =
  • Getting a variable starts with $
# Set string variable
=hello: world

# Set number variable
=number: 1

# Set bool variable
=hello: true

# Set object variable
=hello:
  a: 1
  b: 2

# Set object one liner syntax
=hello: { a: 1, b: 2 }

# Set array variable
=hello:
  - 1
  - 2

# Set array one liner syntax
=hello: [1, 2]

# Set array index
=hello[0]: 3

# Set variable from other variable
=hello: world
=bye: $hello

# Set object value from other variable
=hello: world
=bye:
  name: $hello

# Set array index from other variable
=hello: world
=bye:
  - $hello

# Set variable, nested, dot notation
=hello.name: world

# Delete variable, making $hello undefined
=hello: null

# Delete value from object
=hello:
  name: null

# Delete value from object, dot notation
=hello.name: null

# Delete array index, dot notation
=hello[0]: null

# Set variable from object, dot notation
=hello:
  name:
    deep: 1
=bye: $hello.name.deep

# Set variable from array, dot notation
=hello:
  - 1
  - 2
=bye: $hello[0]

# Set variable from object array, dot notation
=hello:
  - name: nils
=bye: $hello[0].name

# Non existing variables are empty strings
=bye: $hello

# Set literal '$', prevents var lookup
=bye: $$hello

# Setting the same object variable merges the values
=hello: { a: 1 }
=hello: { b: 2 }

@log: $hello
# { a: 1, b: 2 }

If then else

Minimal logic is achieved through @if, @then and @else:

# If with then
@if:
  $hello:
    name:
      eq: nils
@then:
  =hello.name: hans

# Multiple checks
@if:
  $hello:
    name:
      eq: nils
  $req:
    pathname:
      eq: /hello
@then:
  =hello.name: hans

# Checks works with dot notation as well
@if:
  $hello.name.eq: nils
@then:
  =hello.name: hans

# If then else
@if:
  $hello:
    name:
      eq: hans
@then:
  =hello.name: guro
@else:
  =hello.name: kari

The validations inside the if-section are from the d8a validations:

required: true # Can not be undefined
eq: 5          # Equal to
ne: 5          # Not equal to
gt: 5          # Greater than
lt: 5          # Less than
gte: 5         # Greater than or equal to
lte: 5         # Less than or equal to
in:            # Must be in list
  - 1
  - 2
  - 3
nin:           # Must not be in list
  - 1
  - 2
  - 3
length: 5      # Length of string must be
min: 5         # Minimum length of string
max: 5         # Maximum length of string
match: /regex/ # Must match regex
is: boolean    # Must be true or false
is: string     # Must be a string
is: number     # Must be a number, integer or decimal (float)
is: integer    # Must be an integer
is: decimal    # Must be a decimal number
is: date       # Must be a date
is: id         # Must be an id
is: object     # Must be an object
is: array      # Must an array
is: email      # Must be an email address
is: url        # Must be a URL
is: undefined  # Must be undefined
is: null       # Must be null

# Multiple types
is: [string, number]

# Use 'isnt' as the opposite of 'is'
isnt: null

# Works for all of the ones in 'is'
isnt: string
isnt: number
isnt: [email, id]

Return

The @return command sets a variable in state.return. Using @return causes execution to be halted.

# Return a string
@return: hello

# Return a string variable
=hello: world
@return: $hello

# Return an object variable
=hello:
  name: world
@return: $hello

# Return an array variable
=hello:
  - 1
  - 2
@return: $hello

# Return a variable, dot notation
=hello:
  name:
    baner: 1
@return: $hello.name

Vars

You can prefill the state with your own variables:

let req = { pathname: '/hello' }
let state = await weblang
  .init({ vars: { req }})
  .run(code)

Extensions

Weblang can (and should) be extended with your own commands.

Define an extension function like this:

// Extension function called db
function db({
  state,    // the runner's state with vars and return
  code,     // the actual code sent to weblang, untouched
  tree,     // the syntax tree like object, with ids
  branch,   // the current object being processed
  node,     // the key of the current branch
  current,  // the value of the current branch
  key,      // the setter key, usually starts with '='
  id,       // the internal id of the node
  run,      // the run function that runs your code
  opt,      // the options passed to weblang
  expand,   // the expander function used internally
  load,     // the loader, converts yml string to object
  get,      // use this to get variables and run pipes
  set,      // use this to set variables
  ok        // the validation function used for if tests
}) {

  // Example use of set
  set('=internal', 'hello')

  // Whatever you return will be in your setter
  return { id: '1' }
}

Write some code like this:

var code = '@db: user/create'

then run the code like this, while also adding the extension:

let state = await weblang.init({ ext: { db } }).run(code)

To set the result of the function, use the extension variable setter syntax:

=result@db: user/create

and the result variable will be available in state.vars.result.

Pipes

Variables can be run through pipes, which are functions that transform a value.

If the pipe does not exist, it is ignored.

# Use pipes with string
=hello: hello | upcase

# Use pipes with variables
=hello: hello
=bye: $hello | upcase

# Use pipes with return
@return: hello | capitalize

# Multiple pipes
@return: hello | upcase | downcase | capitalize

# Pipe parameters
@return: list | join delimiter=+ max=5

You can add your own pipes, or replace the built in ones, using the pipes option:

// Add a pipe named 'hello'
let state = await weblang
  .init({
    pipes: {
      hello: function({ val }) {
        if (typeof val != 'string') return val
        return 'hello ' + val
      }
    }
  })
  .run(code)

and then use it like this:

@return: world | hello

The pipes receive all the same variables as with extensions.

License

MIT Licensed. Enjoy!