Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@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
We found that @api-platform/ld demonstrated a healthy version release cadence and project activity because the last version was released less than 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.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.