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

wac-ldp

v1.3.0

Published

Personal hobby project. Based on version 0.6 of https://github.com/inrupt/wac-ldp.

Downloads

19

Readme

wac-ldp

Build Status Coverage Status Greenkeeper badge

A central component for Solid servers, handles Web Access Control and Linked Data Platform concerns.

Code Structure

wac-ldp component diagram)

Entry point

The entry point is src/server.ts, which instantiates a http server, a BlobTree storage, and the core app. This is not drawn in the diagram above.

Storage

The BlobTree storage exposes a carefully tuned interface to the persistence layer, which is similar to the well-known "key-value store" concept, where opaque Blobs can be stored and retrieved, using arbitrary strings as keys. But the BlobTree interface differs from a key-value store interface in that it not only allows writing and reading blobs of data, but also querying 'Containers', which is similar to doing ls on a folder on a unix file system: it gives you a list of the directly contained blobs and containers. This means that if we store all LDP resources inside BlobTree blobs, using the resource path from the http level as the blob's path at the BlobTree level, then implementing LDP GET requests on containers becomes very easy out of the box.

The interface looks as follows (BlobTree in the diagram):

interface BlobTree extends events.EventEmitter {
  getContainer (path: Path): Container
  getBlob (path: Path): Blob
}
interface Node {
  exists (): Promise<boolean>,
  delete (): Promise<void>
}
interface Blob extends Node {
  getData (): Promise<ReadableStream | undefined>
  setData (data: ReadableStream): Promise<void>
}
interface Container extends Node {
  getMembers (): Promise<Array<Member>>
}
interface Member {
  name: string
  isContainer: boolean
}
interface Path {
  constructor (segments: Array<string>)
  toParent (): Path
  toChild (segment: string): Path
  isRoot (): boolean
  toString (): string
  toContainerPathPrefix (): string
  hasSuffix (suffix: string): boolean
  removeSuffix (suffix: string): Path
  appendSuffix (suffix: string): Path
}

Execute Task

The core application code is in src/lib/core/executeTask.ts and given a WacLdpTask (see below), it deals with:

  • calling the functions from src/lib/auth/ to determine whether the request is authorized to begin with
  • calling the functions from the 'operations on content' component (currently only 'RDF').
  • fetching the main resource from storage
  • in the case of Glob, checking authorization to read each of the contained resources, and fetching those
  • in the case of POST to a container, picking a name for the new resource and fetching a handle to that
  • check the ETag of the resource in case an If-Match or If-None-Match header was present on the request
  • given the necessary handle(s) to BlobTree node(s), execute the desired operation from src/lib/core/basicOperations.ts (in the case of PATCH, adding a parameter whether it should be executed append-only)
  • in case of success, producing the WacLdpResult (see below) result for src/lib/api/http/HttpResponder
  • in case of an exception, throwing the appropriate ErrorResult, to be cast to WacLdpResult

Auth

The auth code is in src/lib/auth/ and deals with:

  • determining the webId from the bearer token, and checking the signature, expiry, and audience on the there
  • fetching the apprioriate ACL document from storage and loading that into an in-memory RDF graph
  • based on the webId, find out which access modes should be allowed
  • based on the origin, find out whether at least one of the resource owner has that origin as a trusted app
  • decide if the required access mode is authorized (with a special case for append-only approval of a PATCH)

The Auth Interface looks as follows:

async function determineWebId (bearerToken: string, audience: string): Promise<string | undefined>
async function readAcl (resourcePath: Path, resourceIsContainer: boolean, storage: BlobTree)
async function determineAllowedAgentsForModes (task: ModesCheckTask): Promise<AccessModes>
interface ModesCheckTask {
  aclGraph: any,
  isAdjacent: boolean,
  resourcePath: string
}
interface AccessModes {
  read: Array<string>
  write: Array<string>
  append: Array<string>
  control: Array<string>
}
async function appIsTrustedForMode (task: OriginCheckTask): Promise<boolean>
interface OriginCheckTask {
  origin: string,
  mode: string,
  resourceOwners: Array<string>
}

HTTP

In src/lib/api/http/ are two important classes, one for parsing an incoming http request, and one for constructing an outgoing http response. Although each step they do, like setting a numeric http response status code, or extracting a bearer token string from an authorization header, is computationally simple, a lot of the correctness of this module (looking at https://github.com/w3c/ldp-testsuite and the WAC test suite that is under development) depends on the details in these two files.

interface WacLdpTask {
  isContainer: boolean
  omitBody: boolean
  parsedContentType: ParsedContentType | undefined
  origin: string | undefined
  contentType: string | undefined
  ifMatch: string | undefined
  ifNoneMatchStar: boolean
  ifNoneMatchList: Array<string> | undefined
  bearerToken: string | undefined
  wacLdpTaskType: TaskType
  path: Path
  requestBody: string | undefined
}
enum TaskType {
  containerRead,
  containerMemberAdd,
  containerDelete,
  globRead,
  blobRead,
  blobWrite,
  blobUpdate,
  blobDelete,
  getOptions,
  unknown
}
enum ParsedContentType {
  RdfJsonLd,
  RdfTurtle
}
interface WacLdpResponse {
  resultType: ResultType
  resourceData: ResourceData | undefined
  createdLocation: string | undefined
  isContainer: boolean
}

RDF

The following operations are available:

  • readFromBlob (looks at the content-type and the body and reads these into an in-memory RDF graph object)
  • readFromContainer (looks at the container member list and reads that into an in-memory RDF graph object)
  • writeToBlob (serializes an RDF graph object to the requested representation)
  • applyPatch
  • applyFilter

Currently supported representations for RDF are Turtle and JSON-LD. The only currently allowed patch type for RDF are SPARQL-update (any) and SPARQL-update (appendOnly). The currently allowed filter types for RDF are SPARQL-SELECT, ldp-paging, and prefer-minimal-container. In the future, we might add similar modules for e.g. HTML/RDFa or partial updates to binary blobs, and when that happens we will turn this component into an abstract 'content operations' component, of which RDF, HTML/RDFa and Binary are instantiations.

Published as a hobby project, under MIT license, by Michiel de Jong. Based on version 0.6 of https://github.com/inrupt/wac-ldp.