
Product
Announcing Socket Fix 2.0
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
@api-platform/ld
Advanced tools
Rich JSON formats such as JSON-LD use IRIs to reference embeded data. This library fetches the wanted Linked Data automatically.
I have an API referencing books and their authors, GET /books/1
returns:
{
"@id": "/books/1",
"@type": ["https://schema.org/Book"],
"title": "Hyperion",
"author": "https://localhost/authors/1"
}
Thanks to @api-platform/ld
you can load authors automatically when you need them:
import ld from '@api-platform/ld'
const pattern = new URLPattern("/authors/:id", "https://localhost");
const books = await ld('/books', {
urlPattern: pattern,
onUpdate: (newBooks) => {
log()
}
})
function log() {
console.log(books.author?.name)
}
log()
npm install @api-platform/ld
Use ld
like fetch
and specify the URLPattern to match IRIs that are going to be fetched automatically:
import ld from '@api-platform/ld'
await ld('/books', {urlPattern: new URLPattern("/authors/:id", "https://localhost")})
Available options:
fetchFn
fetch function, defaults to fetch().then((res) => res.json())
urlPattern
the url pattern filterrelativeURIs
supports relative URIs (defaults to true
)onUpdate: (root, options: { iri: string, data: any })
callback on data updateonError
error callback on fetch errorsURLPattern is available as a polyfil at https://www.npmjs.com/package/urlpattern-polyfill
import ld from "@api-platform/ld";
import {useEffect} from "react"
import {createRoot} from "react-dom/client"
import {
QueryClient,
useQuery,
QueryClientProvider,
} from '@tanstack/react-query'
const queryClient = new QueryClient();
const pattern = new URLPattern("/(books|authors)/:id", window.origin);
function Books() {
const {isPending, error, data: books} = useQuery({
queryKey: ['/books'],
notifyOnChangeProps: 'all',
queryFn: ({queryKey}) => ld(queryKey, {
urlPattern: pattern,
onUpdate: (root, {iri, data}) => {
queryClient.setQueryData(queryKey, root)
}
})
})
if (isPending) return 'Loading...'
if (error) return 'An error has occurred: ' + error.message
return (
<ul>
{books.member.map(b => (<li data-testid="book">{b?.title} - {b?.author?.name}</li>))}
</ul>
);
}
function App() {
return (
<QueryClientProvider client={queryClient}>
<Books />
</QueryClientProvider>
)
}
createRoot(root).render(<App />)
import { useState, useEffect } from "react";
import { createRoot } from "react-dom/client";
import ld from "@api-platform/ld";
function App() {
const pattern = new URLPattern("/(books|authors)/:id", window.origin);
const [books, setBooks] = useState({});
useEffect(() => {
let ignore = false;
setBooks({});
ld('/books', {onUpdate: (books) => setBooks(books), urlPattern: pattern})
.then(books => {
if (!ignore) {
setBooks(books);
}
});
return () => {
ignore = true;
};
}, []);
return (
<ul>
{books.member?.map(b => (<li data-testid="book">{b.title} - {b.author?.name}</li>))}
</ul>
);
}
const root = createRoot(document.getElementById("root"));
root.render(<App />);
import ld from "@api-platform/ld";
const pattern = new URLPattern("/(books|authors)/:id", window.origin);
const list = document.getElementById('list')
function onUpdate(books) {
const l = []
books.member.forEach((book) => {
const li = document.createElement('li')
li.dataset.testid = 'book'
li.innerText = `${book.title} - ${book.author?.name}`
l.push(li)
});
list.replaceChildren(...l)
}
ld('/books', {urlPattern: pattern, onUpdate, fetchfn: (url, options) => axios.get(url)})
.then((books) => {
books.member.forEach((book) => {
const li = document.createElement('li')
li.dataset.testid = 'book'
li.innerText = `${book.title} - ${book.author?.name}`
list.appendChild(li)
});
})
import ld from "@api-platform/ld";
const pattern = new URLPattern("/(books|authors)/:id", window.origin);
const list = document.getElementById('list')
function onUpdate(books) {
const l = []
books.member.forEach((book) => {
const li = document.createElement('li')
li.dataset.testid = 'book'
li.innerText = `${book.title} - ${book.author?.name}`
l.push(li)
});
list.replaceChildren(...l)
}
ld('/books', {urlPattern: pattern, onUpdate})
.then((books) => {
books.member.forEach((book) => {
const li = document.createElement('li')
li.dataset.testid = 'book'
li.innerText = `${book.title} - ${book.author?.name}`
list.appendChild(li)
});
})
Example of a SWR hook:
import ld, { LdOptions } from '@api-platform/ld'
import useSWR from 'swr'
import {useState} from 'react'
import type { SWRConfiguration, KeyedMutator } from 'swr'
export type fetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
export type Fetcher = (...args: any[]) => Promise<any>
export type onUpdateCallback<T> = (root: T, options: { iri: string, data: object }) => void;
export default function useSWRLd<T extends object>(url: string, fetcher: Fetcher, config: Partial<LdOptions<T>> & SWRConfiguration = {}) {
let cb: undefined | KeyedMutator<T> = undefined
// You may need to force re-rendering as the comparison algorithm of SWR does not work well when object keys are added
// another solution is to improve the compare function
const [, setRender] = useState(false)
const res = useSWR(
url,
(url: RequestInfo | URL, opts: RequestInit) =>
ld(url, {
...opts,
fetchFn: fetcher,
urlPattern: config.urlPattern,
onUpdate: (root) => {
if (cb) {
cb(root, { optimisticData: root, revalidate: false })
setRender((s: boolean) => !s)
}
},
relativeURIs: config.relativeURIs,
onError: config.onError,
}),
config
);
cb = res.mutate
return res
}
FAQs
Fetch Edge Side APIs
The npm package @api-platform/ld receives a total of 17 weekly downloads. As such, @api-platform/ld popularity was classified as not popular.
We found that @api-platform/ld demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.
Product
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.