TriplyDB Publish Implementation¶
Architecture¶
User clicks Publish
↓
PublishDialog.jsx opens
↓
User enters credentials → optional Test Connection
↓
handlePublish() in App.js:
10% — Validate form
30% — Generate TTL (ttlGenerator.js)
50% — Compute graph IRI (buildGraphIRI)
50% — Upload TTL to TriplyDB targeting that graph
85% — Notify backend to re-sync service (graphName included)
100% — Show result + auto-close
↓
publishToTriplyDB() in triplydbHelper.js:
PUT /datasets/{account}/{dataset}/assets (logo, if present)
POST /datasets/{account}/{dataset}/jobs (TTL data,
?defaultGraphName=<URL-encoded IRI>)
↓
updateTriplyDBService() in triplydbHelper.js:
POST {backendUrl}/v1/triplydb/update-service
body: { config, serviceName, graphName }
Files¶
src/
├── App.js # handlePublish() with progress state management
├── components/
│ └── PublishDialog.jsx # Dialog UI: form, progress, success/error states
└── utils/
├── triplydbHelper.js # TriplyDB API integration, buildGraphIRI
└── dmnHelpers.js # sanitizeServiceIdentifier (used by buildGraphIRI)
API functions¶
buildGraphIRI({ organizationIdentifier, serviceIdentifier })¶
Computes the deterministic graph IRI for a publish.
const graphIRI = buildGraphIRI({
organizationIdentifier: organization.identifier,
serviceIdentifier: service.identifier,
});
// → 'https://regels.overheid.nl/graphs/Sociale_Verzekeringsbank/aow-leeftijd'
Parameters:
organizationIdentifier— Full URI (e.g.https://organisaties.overheid.nl/28212263/Sociale_Verzekeringsbank) or local identifier. The helper extracts the last path segment as the local org name.serviceIdentifier— Service identifier (e.g.aow-leeftijd). Sanitised viasanitizeServiceIdentifierfromdmnHelpers.js.
Fallback: Returns https://regels.overheid.nl/graphs/default when either argument is missing. The editor's publish form requires both fields, so the fallback is defensive only.
publishToTriplyDB(ttlContent, config, filename, graphIRI)¶
Uploads TTL content to TriplyDB, targeting a specific graph.
const result = await publishToTriplyDB(
ttlContent,
config,
filename,
graphIRI,
);
// Returns: { success: true, message: "Published successfully! View at: ...", url: "..." }
Parameters:
ttlContent— Generated Turtle stringconfig.baseUrl— TriplyDB API base URLconfig.account— Account/organisation nameconfig.dataset— Target dataset nameconfig.apiToken— API token (transmitted via Authorization header over HTTPS only)filename— Filename for the upload job (e.g.aow-leeftijd.ttl)graphIRI— Target graph IRI frombuildGraphIRI; defaults tohttps://regels.overheid.nl/graphs/default
Network: A single POST to the TriplyDB jobs endpoint with defaultGraphName=<URL-encoded IRI> in the query string. The dataset must already exist; create it manually in TriplyDB before first use. A publishToTriplyDB_SPARQL variant exists for SPARQL UPDATE flows and accepts the same graphIRI parameter with the same default.
updateTriplyDBService(config, serviceName, graphName)¶
Notifies the LDE backend to re-sync the dataset's SPARQL service after a publish.
Parameters:
config— Same shape as forpublishToTriplyDBserviceName— Target service to sync (defaults toconfig.dataset)graphName— IRI of the graph that just received data; logged by the backend astriggeredByGraphfor traceability
The TriplyDB sync API the backend wraps (POST /datasets/{account}/{dataset}/services/{serviceName} with body {"sync":"true"}) has no graph-scoping mechanism — graphName is observability metadata only. The sync re-indexes all graphs the service is configured for.
testTriplyDBConnection(config)¶
Verifies credentials without uploading data.
const result = await testTriplyDBConnection(config);
// Returns: { success: true, message: "Successfully connected to TriplyDB" }
Token storage¶
The API token is stored in localStorage under a namespaced key. It is read when the dialog opens and cleared when the user explicitly removes it. It is transmitted only to the configured TriplyDB base URL over HTTPS — never logged or sent elsewhere.
Graph naming¶
Each publish writes the TTL to a graph whose IRI is computed deterministically from the organisation and service identifiers:
For example, publishing the SVB AOW-leeftijd service yields:
The IRI is computed by buildGraphIRI and passed to publishToTriplyDB from handlePublish in App.js. The same IRI is forwarded to the backend as the graphName field on /v1/triplydb/update-service, where it surfaces in logs as triggeredByGraph.
Effect on republishing. Because the graph IRI is deterministic, republishing the same service overwrites the previous graph rather than creating an incremented graph:default-N. The TriplyDB UI shows one graph per service, named after the service.
Effect on multi-service datasets. A single TriplyDB dataset (e.g. DMN-discovery) can host many services, each in its own graph. The dataset's SPARQL service spans all of them, so cross-service queries continue to work without additional configuration.
Legacy graphs. Services published before the buildGraphIRI feature were all written to the auto-numbered graph:default-N series. These are harmless but can be removed manually from the TriplyDB UI when convenient.
Backend proxy¶
The proxy endpoint is {backendUrl}/v1/triplydb/update-service. Request body:
{
"config": {
"baseUrl": "https://api.open-regels.triply.cc",
"account": "stevengort",
"dataset": "DMN-discovery",
"apiToken": "..."
},
"serviceName": "DMN-discovery",
"graphName": "https://regels.overheid.nl/graphs/Sociale_Verzekeringsbank/aow-leeftijd"
}
graphName is the IRI just written to. The backend logs it for traceability and echoes it in the response when supplied. The actual TriplyDB sync re-indexes all graphs the service spans.
If the proxy is unavailable, the upload still succeeds. A warning is shown: "Service update failed — data is accessible in TriplyDB but the SPARQL endpoint may not reflect the latest state." The proxy is optional; the upload itself does not depend on it.
Backend proxy deployment checklist¶
- Deploy Node.js backend (linked-data-explorer repository)
- Set
TRIPLYDB_TOKENenvironment variable - Configure CORS to allow the editor's domain
- Verify:
curl {backendUrl}/v1/triplydb/healthreturns 200 - Verify TriplyDB connectivity from the backend host