Skip to content

TypeScript

The npm package ships JavaScript ES modules and matching .d.ts declarations. Use the JavaScript / TypeScript tabs throughout this guide for API calls; TypeScript infers their types from the same imports. No separate @types package is needed for DataHubClient.

Setup

Install the package in your application:

npm install @nfdi4plants/datahub-client
npm install --save-dev typescript

Node.js

Use a Node.js runtime with native fetch. Install Node's types and enable ES modules in your application's package.json:

npm install --save-dev @types/node
npm pkg set type=module

For a standalone application with sources in src/, use this tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "verbatimModuleSyntax": true,
    "noEmitOnError": true,
    "types": ["node"],
    "rootDir": "src",
    "outDir": "dist"
  },
  "include": ["src/**/*.ts"]
}

Save your program as src/index.ts, then compile and run it:

npx tsc
node dist/index.js

Keep the .js suffix on the package's deep imports, even inside .ts files. TypeScript resolves the corresponding declarations; the emitted JavaScript loads the .js module.

Browser applications

Keep your framework's TypeScript configuration. For a standalone browser app using a bundler such as Vite, a minimal tsconfig.json is:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "lib": ["ES2022", "DOM"],
    "types": [],
    "strict": true,
    "verbatimModuleSyntax": true,
    "noEmit": true
  },
  "include": ["src/**/*.ts"]
}

Run npx tsc to check types and your bundler to build the application. These settings follow TypeScript's distinction between Node.js and bundler module resolution. DataHubClient uses the browser's fetch; cross-origin requests still require the DataHub to allow your application's origin through CORS.

Inferred types

Create a client using the same imports as JavaScript:

import { DataHubClient } from "@nfdi4plants/datahub-client";
import { Authentication } from "@nfdi4plants/datahub-client/Http/Authentication.js";

const client = new DataHubClient(
  "https://hub.example", Authentication.Anonymous());

Replace https://hub.example with your DataHub URL. Anonymous authentication reads public resources; see authentication for private resources.

  const project = await client.Projects.GetAsync(42); // Project
  const name = project.Name;                        // string
  const description = project.Description ?? "No description";
  console.log(name, description);

GetAsync returns Promise<Project>, so await gives you a Project with typed properties and editor completion. Description is optional (string | undefined). You only need to import the Project type when you name it in your own code. This is ordinary TypeScript inference.

Collection results are native arrays:

  const projects = await client.Projects.ListAsync(); // Project[] (one page)
  const names = projects.map(project => project.Name); // string[]
  console.log(projects.length, names);

Use array methods, indexing, and .length directly. Projects.ListAsync returns one page; use Projects.ListAllAsync when you need every page.

Explicit types for your own functions

Use import type to annotate parameters or return values with the library's model types:

import type { Project } from "@nfdi4plants/datahub-client/Models/Project.js";

function projectLabel(project: Project): string {
  return `${project.PathWithNamespace}: ${project.Name}`;
}

Call it with an inferred result:

  console.log(projectLabel(project));

Model types live under Models/, such as Models/Project.js and Models/Issue.js. The package root exports DataHubClient. A type-only import is removed from emitted JavaScript. Use a regular import when you need the class at runtime, for example to call new Project(...) or use instanceof.

Browser downloads

The shared RO-Crate guide covers fetching metadata and saving it in Node.js or the browser. For a browser helper written in TypeScript, annotate its parameters and return type. Save this as browser.ts:

import type { DataHubClient } from "@nfdi4plants/datahub-client";

/** Download an ARC's JSON-LD metadata using the browser's save-file flow. */
export async function downloadROCrate(client: DataHubClient, projectId: number): Promise<void> {
  const metadata = await client.Packages.DownloadROCrateAsync(projectId);
  const blob = new Blob([metadata], { type: "application/ld+json;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = "arc-ro-crate-metadata.json";
  link.hidden = true;
  document.body.append(link);
  try {
    link.click();
  } finally {
    link.remove();
    // Give the browser time to start the download before releasing its URL.
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  }
}

Then use it from your application's TypeScript entry point:

import { DataHubClient } from "@nfdi4plants/datahub-client";
import { Authentication } from "@nfdi4plants/datahub-client/Http/Authentication.js";
import { downloadROCrate } from "./browser.js";

const client = new DataHubClient("https://git.nfdi4plants.org", Authentication.Anonymous());
const button = document.createElement("button");
button.textContent = "Download RO-Crate";
button.addEventListener("click", () => {
  downloadROCrate(client, 42).catch(console.error);
});
document.body.append(button);

Replace the example DataHub URL and project ID with your own. The ./browser.js import resolves to browser.ts during type checking and to the emitted module at runtime. Keep filesystem imports such as node:fs/promises in Node.js code; browser saving uses Blob and an object URL.