Linked Data Objects: Typescript RDF Devtool

Hi all,

I just wanted to share my new JavaScript library: Linked Data Objects (LDO). Dealing with RDF was always frustrating for me. I just want to be able to read and modify RDF like it was JSON, and I’d like it to be strongly typed.

LDO takes ShEx schema and converts them into TypeScript Typings. You can then use those typings to parse RDF data and modify it as if it were a regular JSON object.

Check it out here:

9 Likes

I’ve had a quick look at this, and it looks very interesting indeed! Have you seen the graphql codegen tools at all?

We, Inrupt, also have an alpha product called Artifact Generator which can generate typescript & java types for vocabularies.

This looks super interesting.
I need to update my ShEx usage and take it on a spin! I bet development will be afterwards easy and fast. :star_struck:

@jaxoncreed i’ve tried with vuejs2 but encountered some error with vue-loader. Do you have a vuejs working example?

I just want to give a shout-out to this library, and to @jaxoncreed for the great work. With the 1.x release, and support for language strings, it fulfills basically all my needs for reading and saving RDF data in Solid documents. It’s brilliant and i love it.

:tada: :heart: :rocket: :slightly_smiling_face:

Check it out if you haven’t already :wink:

3 Likes

I followed your tutorial but in step 3, after run: npm run build:ldo ; I don’t have foafProfile.ldoFactory.ts for next steps.
I tried many many times but not working.
Do you have solution for this problem?
Thank you for such a great tool!

@tranbau you’ve probably seen it already: it was resolved in the issue you opened:

The factory is no longer used. If you want to use older versions of LDO then be sure your instance of ldo-cli is under 3.

Oh, sorry, I forgot that I had posted that question! :blush: But I thought that FoafProfileFactory helped us parse our raw data(RDF) to display them more easily. Is there an alternative way without using it?

@tranbau

This is how i typically use it:

import { fetch } from '@inrupt/solid-client-authn-browser'
import {
  parseRdf,
  toSparqlUpdate,
  toTurtle,
  startTransaction,
  commitTransaction
} from 'ldo'
import { foaf, rdf } from 'rdf-namespaces'
import { FoafProfileShapeType } from './ldo/foafProfile.shapeTypes'
// FoafProfileShapeType needs to be generated by ldo-cli first, based on the shape you provide

const example = async () => {
  // fetch (turtle) document from uri
  const uri = 'https://example.com/profile/extended' // uri of document (hashes are ok)
  const uriOfThing = 'https://example.com/profile/card#me' // uri of thing we want to read
  // often these two uris are the same
  // or you might not need uriOfThing, if you find it by matching predicate and/or object...

  // fetch the (turtle) document first
  const response = await fetch(uri)
  const doc = await response.text()

  // use ldo to parse it
  const ldoDataset = await parseRdf(doc, { baseIRI: uri })
  const profile = ldoDataset
    .usingType(FoafProfileShapeType)
    .fromSubject(uriOfThing)
    // uri of subject, in this case it would probably be person's webId

  // OR you can find the thing by matching its predicate and object
  // matcher returns array of matched things
  const alsoProfiles = ldoDataset
    .usingType(FoafProfileShapeType)
    .matchSubject(rdf.type, foaf.PersonalProfileDocument)
  // there is also matchObject method

  // now you can use the profile like normal TypeScript/JavaScript object
  const name = profile.name
  const friends = profile.knows?.map(friend => friend['@id'])
}

You can also create or modify the object with PATCH

const ldoDataset = await parseRdf(doc, { baseIRI: uri })
// or for new thing
const ldoDataset = createLdoDataset()
const profile = ldoDataset
    .usingType(FoafProfileShapeType)
    .fromSubject(uriOfThing)
startTransaction(profile)
profile.name = 'New Name'

const patch = await toSparqlUpdate(profile)
// and you can send the patch to the server now
await fetch(uri, {
  method: 'PATCH',
  body: patch,
  headers: { 'content-type': 'application/sparql-update' }

BUT! Please keep in mind that PATCH application/sparql-update is not specified in Solid Protocol, so it may not be supported. So instead we can do PATCH with text/n3

// you need to do this BEFORE committing transaction
const n3patch = await toN3Patch(profile)
// and you can send the patch to the server now
await fetch(uri, {
  method: 'PATCH',
  body: n3patch,
  headers: { 'content-type': 'text/n3' }
})

// where i defined toN3Patch myself, based on
// https://solidproject.org/TR/protocol#n3-patch
// but i hope it will be included in the library:
import { Dataset } from '@rdfjs/types'
import { transactionChanges } from 'ldo'
import { datasetToString } from 'ldo/dist/datasetConverters'
import { LdoBase } from 'ldo/dist/util'

export async function toN3Patch(ldo: LdoBase): Promise<string> {
  const changes = transactionChanges(ldo)
  const patch = `
      _:patch a <${solid.InsertDeletePatch}>;
        <${solid.inserts}> { ${
    changes.added
      ? await datasetToString(changes.added as Dataset, { format: 'N3' })
      : ''
  } };
        <${solid.deletes}> { ${
    changes.removed
      ? await datasetToString(changes.removed as Dataset, { format: 'N3' })
      : ''
  } }.`
  return patch
}

Or, if you want to use POST or PUT instead,

// first, commit the transaction
commitTransaction(profile)
const doc = await toTurtle(profile)
// and send it to server with PUT or POST

You’ll find more examples in LDO repository README.

i’m not affiliated with this library. i just like to use it.
the above code hasn’t been run, mistakes have been included :wink:

1 Like

Thank you for the detailed instructions. But now I have another question that when i run npm run build:ldo , it just print the result in terminal like :
{
id: ‘https://ldo.js.org/MedicationStatement’,
type: ‘ShapeDecl’,
shapeExpr: {
type: ‘Shape’,
expression: { type: ‘EachOf’, expressions: [Array] },
extends: [ ‘https://ldo.js.org/DomainResource’ ],
closed: true
}
},
… 2 more items
]
}
}
instead of ts files
Do you know why?

Sorry, i don’t know that… :confused: Maybe you could open an issue in the project repository, and provide some additional context there. You were able to generate those files before, weren’t you?

I found that my schema has some problems :slight_smile: sr my bad!

Hi there, great job!

I think I have developed something related for the Data Food Consortium: GitHub - datafoodconsortium/connector-typescript: The connector makes things easier when integrating with DFC. This is the TypeScript version.

The DFC is building a semantic standard for the short supply chains. I’m currently proposing a client-to-client standard to make it SOLID compliant.

The DFC connector allows to create objects (with the new operator or by using a factory) that are mapped to the DFC ontology. It is also able to load and export data from and to JSON-LD. And finally it allows to navigate through linked data dynamically (lazy loading).

We are generating the connector from an UML model into different languages (TypeScript and Ruby for now) thanks to Acceleo, a model-to-text transformer within Eclipse.

One big question that remains when building a SOLID app is where to put the logic. We need to compute things like values (eg: the total price of an order can be calculated by adding the price of all its lines). It would be nice to have some method to get that value (eg: getTotalPrice). The idea is to put that method into the object model so we can call something like order.getTotalPrice() that would lazy load the order lines and compute the total price.

We need also plenty other tools to build a complete SOLID app and a SOLID framework will probably emerge some day.

@jaxoncreed @mrkvon How do you manage the logic with LDO?

1 Like

UPDATE:
Building Solid Apps with LDO. Solid is a decentralized web framework… | by Jackson Morgan | Medium / GitHub - jaxoncreed/ldo-react-tutorial-1: An LDO tutorial for React is deprecated, right @jaxoncreed?

We should use For Solid+React - Linked Data Objects (LDO) / GitHub - o-development/ldo-tutorial-solid-react: A tutorial for building a Solid React app using LDO. instead. right?

1 Like