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

arbase

v0.2.2

Published

Arbase is a tool to create object-based APIs on top of arweave in mere minutes

Downloads

8

Readme

arbase

Arbase is a tool to create object-based APIs on top of arweave in mere minutes

What does it do?

It allows you to generate APIs from a simple JSON format

Example

{
  "post": { // let's first create a post
    "attributes": { // it's got some attributes
      "title": { // like a titlte
        "type": "string", // ...which is a string
        "maxSize": 1000, // ...that's limited to 1k characters
        "notNull": true, // ...and can't be empty
        "modify": [ // it can only be modified by the creator and the moderators
          "$.creator", // we use $ to reference the current object. in this case the creator of it
          "$~moderators" // and the moderators of this post
        ]
      },
      "content": { // every post also has content, which has basically the same rules
        "type": "string",
        "maxSize": 10000, // ...except it's 10k chars long
        "notNull": true,
        "modify": [
          "$.creator",
          "$~moderators"
        ]
      },
      "replies": { // then we have the replies
        "type": "post[]", // that's basically a list of posts (posts can have their own replies, like in reddit or discourse - really, just different rendering)
        // this list doesn't have a maxSize, since they can be grown infinetly without too much impact (TODO: really good idea?), but technically it can be set
        // notNull is also not set, since posts usually are created without replies
        "append": [ // this says who can reply
          "$.creator", // we can reply to our own stuff of course
          "*", // anyone else can as well (wildcard = "anyone")
          "!#~blacklisted", // but blacklisted users can't (this basically translated to "NOT (!) previous element (#) access control (~) blacklisted")
        ],
        "delete": [ // this says who can delete replies
          "$$.creator", // users can remove their own replies ($$ references the object in the list)
          "#"
        ]
      },
      "acl": { // we'll get to that later
        "moderators": { // for now just know: it allows moderators of the topic to moderate this post
          "fixed": [
            "#~moderators"
          ]
        }
      }
    }
  },
  "topic": { // now let's make the topics
    "attributes": {
      "title": { // every topics has a title
        "type": "string",
        "maxSize": 1000,
        "notNull": true,
        "modify": [ // it can be modified by the moderators
          "$~moderators"
        ]
      },
      "description": { // and a short description
        "type": "string",
        "maxSize": 1000,
        "notNull": true,
        "modify": [ // it can be modified by the moderators as well
          "$~moderators"
        ]
      },
      "posts": { // also it can contain posts, similar to replies
        "type": "post[]",
        "append": [
          "*", // again everyone can reply to it
          "#~blacklisted" // except blacklisted users
        ]
      },
      "topics": { // and it can contain sub-topics
        "type": "topic[]",
        "append": [ // ..which only moderators can add
          "$~moderators"
        ],
        "delete": [
          "$~moderators" // ...and only moderator can remove
        ]
      }
    },
    "acl": { // access control lists. this is where the permission magic happens
      "moderators": { // we have a moderators list
        "initial": [ // initially it contains the creator
          "$creator"
        ],
        "fixed": [ // permanently it contains the sub-topic moderators
          "#~moderators"
          // TODO: possibly add "$~blacklisted" ?
        ],
        "append": [ // anyone can append who's already a moderator
          "$~moderators"
        ],
        "delete": [ // same goes for deleting (you can de-mod yourself for e.x.)
          "$~moderators"
        ]
      },
      "blacklisted": { // the blacklisted users list
        "fixed": [
          "#~blacklisted" // include users that are blacklisted in the previous element
        ]
      }
    }
  },
  "board": { // this is our board
    "attributes": {
      "name": { // every board has a name
        "type": "string",
        "maxSize": 1000,
        "notNull": true,
        "modify": [ // it can be modified by the moderators
          "$~moderators"
        ]
      },
      "description": { // and a short description
        "type": "string",
        "maxSize": 1000,
        "notNull": true,
        "modify": [ // it can be modified by the moderators as well
          "$~moderators"
        ]
      },
      "topics": { // and it can contain topics
        "type": "topic[]",
        "append": [ // ..which only moderators can add
          "$~moderators"
        ],
        "delete": [
          "$~moderators" // ...and only moderator can remove
        ]
      }
      // basically like a topic, except it can't contain posts
    }
    "acl": { // here the acl are a little bit different
      "moderators": {
        "fixed": [ // the creator is an irremovable moderator
          "$creator"
        ],
        "append": [
          "$~moderators"
        ]
      },
      "blacklisted": {
        "fixed": [ // also the creator can never be blacklisted
          "!$creator"
        ],
        "append": [
          "$~moderators"
        ]
      }
      // and the previous references are missing, since this is the main element
    }
  },
  "@main": "board" // this tells the crud api that "board" is the base element. as such it's not allowed to contain any "#" references
}
// also noticed how we're not using any time elements? the time is always available via $.createdOn or $.updatedOn, since we're using a blockchain beneath
// sidenote: ## is "previous of previous" in the tree

Good to know

  • The $.creator permission might be dangerous
    • It is valid even when a blacklist entry applies in specific conditions. Therefore it's better to not add it when using anyone (*), or make it the initial content of an acl, so it can be revoked later when needed.

Todo

Now

  • [ ] Base object
  • [ ] ARQL fetch
  • [ ] OPLog
  • [ ] Lists
  • [x] @imports: Basically "@imports": { "namespace": "npm:some-cool-scheme/db.json", "namespace-2": "fs:./other-thing.json" }, so that we can do for ex namespace:thing[] or namespace:thing

Future

  • ACLs
  • Rate-limiting
  • Native "file" field that links to an arweave file-block

Backwards compatibility

  • The removal of an attribute causes it to simply be ignored on verification, so attributes can be safely deleted
    • Note that all elements that do not contain at least one valid attribute are ignored. But this shouldn't be an issue since they are obsoleted in that case, except if the creation is followed by edits that do introduce valid elements)
  • The change of an ACL initial/fixed set could invalidate entries if not done carefully
  • Same goes for the removal of a complete ACL
  • The addition of an ACL usually doesn't change anything