Skip to content

Implement urn:solid resolver for pane type-matching #8

@melvincarvalho

Description

@melvincarvalho

Follow-up to #6, now that the upstream piece (the reverse index) is published.

What changed since #6

The urn-solid registry now publishes a reverse-lookup table at https://urn-solid.github.io/reverse-index.json — ~467 entries mapping each upstream IRI (foaf:, schema:, dcterms:, etc.) back to its canonical `urn:solid:` form. This is the data piece the resolver was waiting on.

What this issue asks for

Add a small resolver module + pane registry to LOSOS that uses the reverse index to canonicalise incoming `@type` and predicate keys at read time. Once shipped, every existing LOSOS app retroactively becomes readable by every other LOSOS app, regardless of which upstream vocabulary the source used. No app migration required — the canonicalisation is read-side.

Sketch (~80 lines total)

```js
// urn-solid-resolver.js
const REGISTRY_URL = "https://urn-solid.github.io/reverse-index.json\";
let cache = null;
async function loadIndex() {
if (!cache) cache = await fetch(REGISTRY_URL).then(r => r.json());
return cache;
}
const isUrnSolid = s => typeof s === "string" && s.startsWith("urn:solid:");
const isAbsolute = s => typeof s === "string" && /^[a-z][a-z0-9+.-]*:/i.test(s);

function resolve(iri, index) {
if (!iri) return iri;
if (isUrnSolid(iri)) return iri;
if (isAbsolute(iri)) return index[iri] ?? iri;
return "urn:solid:" + iri; // bare name → SHOULD default per LION RDF Compatibility
}

function normalize(obj, index) {
if (Array.isArray(obj)) return obj.map(o => normalize(o, index));
if (obj === null || typeof obj !== "object") return obj;
const out = {};
for (const [k, v] of Object.entries(obj)) {
if (k === "@type") out[k] = Array.isArray(v) ? v.map(t => resolve(t, index)) : resolve(v, index);
else if (k.startsWith("@")) out[k] = v;
else out[resolve(k, index)] = normalize(v, index);
}
return out;
}
```

```js
// PaneRegistry
class PaneRegistry {
constructor() { this.index = null; this.panes = new Map(); }
async ready() { this.index ??= await loadIndex(); }
register(type, pane) {
if (!type.startsWith("urn:solid:")) throw new Error(`expected urn:solid:* type, got ${type}`);
this.panes.set(type, pane);
}
match(incomingType) { return this.panes.get(resolve(incomingType, this.index)); }
}
```

Acceptance

  • `urn-solid-resolver.js` shipped (vendored, no npm dependency).
  • Pane registry uses it for type-matching.
  • At least one existing LOSOS app updated to register against `urn:solid:` types.
  • Demo: open two existing LOSOS apps that wrote data with different upstream vocabs (e.g. one foaf:, one schema:) and watch one pane render data from both.

Open design questions still pending from #6

  1. Where does the index live in the LOSOS bundle — fetched on-demand, vendored snapshot, or both?
  2. Existing pane registrations against upstream IRIs — additive (both supported) or migrate?
  3. Confirm scope to vocabulary terms only (bare form), not subspaced `urn:solid` identifiers.

Honest caveats

  • Assumes pre-expanded JSON-LD. Compact contexts (`"foaf:name"`) need either a JSON-LD expansion pass first or extending `resolve()` to handle prefix:term form.
  • First load fetches the index; subsequent calls cache. Long-running apps need a TTL.
  • One-way (canonicalise on read). If LOSOS ever needs to write data back in the original vocabulary, it has to remember the input form — separate concern.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions