
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@narrative.io/jsonforms-provider-protocols
Advanced tools
Dynamic data provider capabilities for JSONForms with Vue 3 integration
A Vue 3 library that adds dynamic data provider capabilities to JSONForms, enabling form fields to fetch and display data from various sources like REST APIs, databases, and custom protocols.
# Using bun (recommended)
bun add @narrative.io/jsonforms-provider-protocols
# Using npm
npm install @narrative.io/jsonforms-provider-protocols
# Peer dependencies
bun add @jsonforms/vue @jsonforms/core vue
import { createApp } from 'vue'
import ProviderProtocols, { RestApiProtocol } from '@narrative.io/jsonforms-provider-protocols'
const app = createApp(App)
app.use(ProviderProtocols, {
protocols: [RestApiProtocol()]
})
{
"type": "Control",
"scope": "#/properties/country",
"options": {
"provider": {
"ref": "countries",
"protocol": "rest_api",
"config": {
"url": "https://api.example.com/countries",
"items": "$.data[*]",
"map": {
"label": "$.name",
"value": "$.code"
}
}
}
}
}
<script setup lang="ts">
import { JsonForms } from '@jsonforms/vue'
import { providerRenderers } from '@narrative.io/jsonforms-provider-protocols/vue'
import { markRaw, ref } from 'vue'
const data = ref({ country: null })
const handleChange = (event) => data.value = event.data
</script>
<template>
<JsonForms
:data="data"
:schema="schema"
:uischema="uischema"
:renderers="markRaw(providerRenderers)"
@change="handleChange"
/>
</template>
Define how data is fetched and transformed:
const CustomProtocol: Protocol = {
protocol: 'my-api',
async resolve(config, context) {
const response = await fetch(config.url)
const data = await response.json()
return {
items: data.map(item => ({
label: item.name,
value: item.id
})),
ttl: 300
}
}
}
Transform API response data before mapping to form items using a pipeline of transforms:
{
"provider": {
"protocol": "rest_api",
"config": {
"url": "https://api.example.com/data",
"items": "$.data[*]",
"transforms": [
{
"name": "flatten",
"key": "children",
"labelFormat": "{parent.name} → {name}"
},
{
"name": "filter",
"key": "active",
"values": [true]
}
],
"map": {
"label": "$.name",
"value": "$.id"
}
}
}
}
Flatten Transform Recursively flattens nested tree structures into a single-level array:
{
"name": "flatten",
"key": "children",
"labelFormat": "{parent.name} → {name}"
}
key: The property containing nested children arrayslabelFormat (optional): Template for formatting labels using parent and child properties_depth, _parent, and _formattedLabel metadata to itemsFilter Transform Filters items based on property values:
{
"name": "filter",
"key": "category",
"values": ["A", "B"]
}
key: The property to checkvalues (optional): Array of values to match. If omitted, filters by key existenceCombining Transforms Transforms are applied sequentially in pipeline order:
{
"transforms": [
{ "name": "flatten", "key": "children" },
{ "name": "filter", "key": "type", "values": ["product"] }
]
}
Custom Transforms Register custom transforms for your specific needs:
import { registerTransform } from '@narrative.io/jsonforms-provider-protocols'
registerTransform('uppercase', (items, config) => {
return items.map(item => ({
...item,
name: item.name.toUpperCase()
}))
})
Create dynamic URLs using form data:
{
"url": "https://api.example.com/countries/{{data.country}}/states",
"query": { "search": "{{ui.query}}" }
}
Control when data is fetched:
mount - Load when component mounts (default)onFocus - Load when field receives focusquery - Load when user types (autocomplete)Auto-populate fields from form data or external sources:
{
"type": "Control",
"scope": "#/properties/derived_field",
"options": {
"derive": "country",
"mode": "follow",
"readonly": true
}
}
Access external data sources separate from form data using the externalData() syntax:
<script setup>
// Provide external data to the form
const externalData = ref({
user: { preferences: { theme: "dark" } },
tree: { name: "Oak", type: "Deciduous" }
})
provide('externalData', externalData)
</script>
{
"type": "Control",
"scope": "#/properties/tree_preference",
"options": {
"derive": "externalData(tree.name)",
"mode": "follow",
"readonly": true
}
}
Control error display behavior with the showError property:
{
"provider": {
"protocol": "rest_api",
"config": {
"url": "https://api.example.com/data",
"showError": false,
"items": "$.data[*]",
"map": { "label": "$.name", "value": "$.id" }
}
}
}
When showError is false, failed requests return empty results instead of throwing errors. Defaults to true.
Use providers directly in your components:
<script setup>
import { useProvider } from '@narrative.io/jsonforms-provider-protocols/vue'
const { items, loading, error, reload } = useProvider(binding, context)
</script>
# Install dependencies
bun install
# Run tests
bun test
# Build library
bun run build
# Type checking
bunx vue-tsc --noEmit
# Watch mode for development
bun run dev
To test changes locally in a consumer application, use bun link to create a symlink:
In this library:
# Build and create a global link
bun run link:global
In your consumer application:
# Link to the local version
bun link @narrative.io/jsonforms-provider-protocols
Changes to the library will be reflected in the consumer app after rebuilding:
# In this library - rebuild after making changes
bun run build
# Or use watch mode for automatic rebuilds
bun run dev
Verify the build succeeded:
# Check that all dist files exist
bun run check:built
This runs scripts/ensureBuild.js to verify that all expected output files exist in the dist/ directory before linking.
To unlink and use the published package again:
# In your consumer application - remove the symlink and reinstall from npm
rm -rf node_modules/@narrative.io/jsonforms-provider-protocols
bun install
Note:
bun unlink {packageName}is not yet implemented, so manual removal is required.
To create a distributable package for testing:
bun run pack:dist
This creates a .tgz file that can be installed in consumer apps via:
bun add ./path/to/narrative.io-jsonforms-provider-protocols-x.x.x.tgz
Contributions are welcome! Please read our Contributing Guide and check out the issue tracker.
MIT - see LICENSE file for details.
FAQs
Dynamic data provider capabilities for JSONForms with Vue 3 integration
We found that @narrative.io/jsonforms-provider-protocols demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 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.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.