@triply/triplydb
    Preparing search index...

    Changelog

    Notable changes to @triply/triplydb.

    • Dataset.sparqlQuery(queryString) runs a SPARQL query over a dataset's own data. TriplyDB's built-in engine answers it, so the dataset needs no service.

      What it hands back has not sent anything yet — choose a result form on it, and that form is the request: bindings() for a SELECT, statements() for a CONSTRUCT or DESCRIBE, boolean() for an ASK, and toFile(path) for any of them.

      const bindings = await dataset.sparqlQuery("select * { ?s ?p ?o } limit 10").bindings();
      

      Each form is a single request carrying the whole result set, so the object is reusable and every call runs the query again. Asking for a form the query cannot answer in is refused rather than coerced.

      toFile writes a SELECT or ASK as TSV and a CONSTRUCT or DESCRIBE as N-Triples — the query's form decides, not the file name you pass — and gzips when the name ends in .gz, or when you pass { compressed: true }.

    • Service.sparqlQuery(queryString), the same call against a running service, with the same result forms. The service has to be running and to offer a SPARQL endpoint, which an Elasticsearch service does not. It answers from the data it was built with, so one that has fallen behind its dataset keeps answering from the older data until Service.update brings it up to date.

    • Dataset.sparqlUpdate(updateString) applies a SPARQL Update to a dataset. The update is one transaction — either every operation in it takes effect, or none does. It rewrites the dataset's own data, so each of its services keeps serving the older data until you call Service.update.

      await dataset.sparqlUpdate("insert data { <a:s> <a:p> <a:o> }");
      
    • Query.execute(variableValues?) applies a saved query whose text is a SPARQL Update, taking values for its variables and falling back to the query's own defaults. It applies the version the object is on, so Query.useVersion decides which update text runs. Only the built-in engine applies an update, so a query saved to run on a service is refused; Query.results() on update text is likewise refused, pointing here.

    • SparqlResults — the class both sparqlQuery methods return — and the request shapes SparqlQueryInput, SparqlUpdateInput and SparqlRequestInput, all exported from @triply/triplydb.

    • Account.addQuery and Query.addVersion accept SPARQL Update text in queryString, storing it as an update. It was previously rejected, leaving the version saved as invalid.
    • Query.useVersion("latest") refetches the query, so getInfo() afterwards describes the latest version rather than the one that was pinned before. This also fixes Query.addVersion on a pinned query object, which carried the pinned version's settings over into the new version instead of the latest one's.

    A major release: three behaviours changed in ways that can break a caller, each listed below with what to use instead. The additions are mostly the documentation itself — a published reference, and declarations that carry their doc comments into your editor.

    • App.get(idString) is removed, with no deprecation period. The idString notation is incompatible with future TriplyDB account notation for nested groups.

      Use the typed getters instead. They have always been the same code underneath:

      // before                              // after
      app.get("account") app.getAccount()
      app.get("account:my-account") app.getAccount("my-account")
      app.get("user") app.getUser()
      app.get("user:my-user") app.getUser("my-user")
      app.get("group:my-group") app.getGroup("my-group")
      app.get("dataset:my-dataset") (await app.getAccount()).getDataset("my-dataset")
      app.get("query:my-query") (await app.getAccount()).getQuery("my-query")
      app.get("story:my-story") (await app.getAccount()).getStory("my-story")

      The static factory App.get(config) is unchanged and unrelated.

    • IncompatibleError now extends TriplyDbJsError. A single catch (e) { if (e instanceof TriplyDbJsError) … } now catches every error this library throws, including the version-incompatibility one it previously missed. Code that branches on IncompatibleError after a TriplyDbJsError branch will now take the earlier branch — test for IncompatibleError first.

    • Dataset.uploadAsset names an asset after the file, not the path. Passing a path used to create an asset called ./data/logo.png; it is now called logo.png. Pass name explicitly to keep the old value.

    • An API reference at https://static.triply.cc/triplydb-js/
    • import { … } from "@triply/triplydb" now reaches the public surface from one place: the classes, the options types their methods take, and the shapes their getInfo() methods return. The deep paths (@triply/triplydb/Dataset and so on) still work, and import App from "@triply/triplydb" is unchanged.
    • ServiceConfigElastic and ServiceConfigJena, the shapes Dataset.addService takes as config. Their documentation covers what an Elasticsearch service indexes without being configured, and how index and component templates change that.
    • User.accountType, which is "User". Together with Group.accountType it narrows an Account to one or the other without a request.
    • The iterator classes are now named for what they are: AsyncIteratorHelper is ResultIterator and AsyncIteratorHelperWithToFile is QueryResultIterator, each exported from the package root. The old module paths — @triply/triplydb/utils/AsyncIteratorHelper and …/AsyncIteratorHelperWithToFile — still resolve, re-exporting the new classes, so nothing breaks; they carry a deprecation pointing at the replacement.
    • Dataset.importFromFiles no longer waits forever on an upload that goes quiet. A file that makes no progress at all for five minutes fails the import, with an error naming the file and the job to check.
    • Graph.rename returns the graph when the new IRI is the one it already has, as it does for a real rename, instead of undefined.
    • Query.runAsSelectQueryJob throws a TriplyDbJsError on a query that is not a SELECT, like every other failure in this library, instead of a plain Error.
    • fileCache creates its directory when it does not exist, as it was documented to.

    Organizations became groups, and groups gained membership and nesting. Nested groups are an upcoming feature of triplyDB.

    • Groups, as the name for what was called an organization: App.getGroup, User.getGroups, User.getGroup, User.createGroup, User.ensureGroup, Account.asGroup, and a Group class exported from @triply/triplydb/Group.
    • Group membership: Group.getMembers, Group.addMember, Group.removeMember, Group.changeRole and Group.delete.
    • A group's own access level, settable at creation through User.createGroup and User.ensureGroup, and afterwards through Group.update.
    • Nested groups. A group's placement is expressed in its account name, colon-separated, so a subgroup is addressed as parent:child.
    • Group.accountType, which is "Group".
    • Dataset.getInfo takes an options object as well as a boolean, with a signal for aborting the request: getInfo({ refresh: true, signal }).

    Nothing was removed. The organization names still work and now carry a deprecation, so an editor points at the replacement: asOrganization, createOrganization, getOrganizations, getOrganization, ensureOrganization, App.getOrganization, App.get("org:…"), the @triply/triplydb/Org module, and Group.type (use Group.accountType).

    • Account.importDataset failed outright when the target instance had assets switched off. It now copies what it can and carries on.
    • Deep imports written with a .js extension — @triply/triplydb/Dataset.js, as 8.x accepted — stopped resolving when the package moved to an exports map. They resolve again.
    • Creating a saved query failed against TriplyDB 25.12.100 through 26.2.100, which rejected two properties the request carries rather than ignoring them.
    • Account.importDataset failed when the source dataset had topics and the target instance did not support them.
    • Query.runAsSelectQueryJob declared its results as bindings, which they are not — it yields one parsed JSON object per line, the first naming the projected variables.
    • Updated dependencies.
    • Updated dependencies.
    • Updated dependencies.
    • Query.runAsSelectQueryJob, which runs a SELECT query as a batch job and streams the results, so a query too large or slow to page through in process can still be read.
    • Query.update accepts a Dataset for its dataset field, not only a dataset id.
    • Query.getString() threw a TypeError on a saved query with no request payload, instead of the "has no versions" error it means to report.
    • SPARQL Update in saved queries.