# JavaScript SDK

The JS SDK provides an intuitive interface for the Directus API from within a JavaScript-powered project (browsers and node.js). The default implementation uses Axios (opens new window) for transport and localStorage for storing state.

# Installation

npm install @directus/sdk

# Usage

import { Directus } from '@directus/sdk';

const directus = new Directus('https://api.example.com/');

NOTE All methods return promises. Make sure to await methods, for example:

import { Directus } from '@directus/sdk';

const directus = new Directus('https://api.example.com/');

// Wait for login to be done...
await directus.auth.login({
	email: 'admin@example.com',
	password: 'password',
});

// ... before fetching items
const articles = await directus.items('articles').readMany();

console.log({
	items: articles.data,
	total: articles.meta.total_count,
});

# Global

# Initialize

import { Directus } from '@directus/sdk';

const directus = new Directus('https://api.example.com/');

# url

The constructor accepts the URL as the first parameter.

# options.auth

The authentication implementation. See Auth for more information.

Defaults to an instance Auth.

# options.storage

The storage implementation. See Storage for more information.

Defaults to an instance of MemoryStorage when in node.js, and LocalStorage when in browsers.

# options.transport

The transport implementation. See Transport for more information.

Defaults to an instance of AxiosTransport.

# Full Example

const url = 'http://api.example.com/';

// Storage adapter where refresh tokens are stored in JSON mode.
const storage = new MemoryStorage();

// Transport used to communicate with the server.
const transport = new AxiosTransport(url, storage);

// Auth is how authentication is handled, stored, and refreshed.
const auth = new Auth(transport, storage, {
	mode: 'json', // or cookie, depends on your use  case
});

const directus = new Directus(url, {
	auth,
	storage,
	transport,
});

# Get / Set API URL

// Get the API base URL
console.log(directus.url); // => https://api.example.com/

// Set the API base URL
directus.transport.url = 'https://api2.example.com';

# Access to transport/Axios

You can tap into the transport through directus.transport. If you are using the (default) AxiosTransport, you can access axios through directus.transport.axios.

# Items

You can get an instance of the item handler by providing the collection (and type, in the case of TypeScript) to the items function. The following examples will use the Article type.

JavaScript

// import { Directus, ID } from '@directus/sdk';
const { Directus } = require('@directus/sdk');

const directus = new Directus('https://api.example.com');

const articles = directus.items('articles');

TypeScript

import { Directus, ID } from '@directus/sdk';

// Map your collection structure based on its fields.
type Article = {
	id: ID;
	title: string;
	body: string;
	published: boolean;
};

// Map your collections to its respective types. The SDK will
// infer its types based on usage later.
type MyBlog = {
	// [collection_name]: typescript_type
	articles: Article;

	// You can also extend Directus collection. The naming has
	// to match a Directus system collection and it will be merged
	// into the system spec.
	directus_users: {
		bio: string;
	};
};

// Let the SDK know about your collection types.
const directus = new Directus<MyBlog>('https://directus.myblog.com');

// typeof(article) is a partial "Article"
const article = await directus.items('articles').readOne(10);

// Error TS2322: "hello" is not assignable to type "boolean".
// post.published = 'hello';

# Create Single Item

await articles.createOne({
	title: 'My New Article',
});

# Create Multiple Items

await articles.createMany([
	{
		title: 'My First Article',
	},
	{
		title: 'My Second Article',
	},
]);

# Read All

await articles.readMany();

# Read By Query

await articles.readMany({
	search: 'Directus',
	filter: {
		date_published: {
			_gte: '$NOW',
		},
	},
});

# Read By Primary Key(s)

await articles.readOne(15);

Supports optional query:

// One
await articles.readOne(15, { fields: ['title'] });

Supports optional query:

await articles.updateOne(15, { title: 'An Updated title' }, { fields: ['title'] });

await articles.updateMany(
	[
		/*...*/
	],
	{ fields: ['title'] }
);

# Update Multiple Items

await articles.updateMany([
	{
		id: 15,
		title: 'Article 15',
	},
	{
		id: 42,
		title: 'Article 42',
	},
]);

Supports optional query:

await articles.updateMany(
	[
		{
			id: 15,
			title: 'Article 15',
		},
		{
			id: 42,
			title: 'Article 42',
		},
	],
	{ fields: ['title'] }
);

# Delete

// One
await articles.deleteOne(15);

// Multiple
await articles.deleteMany([15, 42]);

# Activity

# Read All Activity

await directus.activity.readMany();

# Read Activity By Query

await directus.activity.readMany({
	filter: {
		action: {
			_eq: 'create',
		},
	},
});

# Read Activity By Primary Key(s)

await directus.activity.readOne(15);

Supports optional query:

await directus.activity.readOne(15, { fields: ['action'] });

# Create a Comment

await directus.activity.comments.create({
	collection: 'articles',
	item: 15,
	comment: 'Hello, world!',
});

# Update a comment

await directus.activity.comments.update(31, {
	comment: 'Howdy, world!',
});

Note: The passed key is the primary key of the comment

# Delete a comment

await directus.activity.comments.delete(31);

Note: The passed key is the primary key of the comment

# Auth

# Configuration

Directus will accept custom implementations of the IAuth interface. The default implementation Auth can be imported from @directus/sdk. The default implementation will require you to pass the transport and storage implementations. All options are optional.

import { Auth } from '@directus/sdk';

// ...

const sdk = new Directus('url', {
	auth: new Auth(transport, storage, options);
	// ...
});

# transport

The transport responsible for communicating with Directus backend.

Defaults to an instance of AxiosTransport when not creating Auth youself.

# storage

The storage responsible for storing authentication and sdk state.

When not creating Auth youself, defaults to MemoryStorage in node.js, and LocalStorage in browsers.

# options.mode

Accepts cookie or json.

When in cookie mode, the API will set the refresh token in an httpOnly secure cookie that can't be accessed from client side JavaScript. This is the most secure way to connect to the API from a public front-end website.

When you can't rely on cookies, or need more control over handling the storage of the cookie (like in node.js), use json mode. This will return the refresh token in the "normal" payload. The storage of these tokens are handled by the storage implementation.

Defaults to cookie in browsers, json in node.js.

# Full example

import { Auth, AxiosTransport, Directus, MemoryStorage } from '@directus/sdk';

const url = 'http://directus';

const storage = new MemoryStorage();
const transport = new AxiosTransport(url, storage);
const auth = new Auth(transport, storage, {
	mode: 'json',
});

const directus = new Directus(url, {
	auth,
	storage,
	transport,
});

await directus.auth.login({
	email: 'admin@example.com',
	password: 'password',
});

# Get current token

const token = directus.auth.token;

# Login

# With credentials

await directus.auth.login({
	email: 'admin@example.com',
	password: 'd1r3ctu5',
});

# With static tokens

await directus.auth.static('static_token');

# Refresh auth token

You can set authentication to auto-refresh the token once it's close to expire.

await directus.auth.login(
	{
		email: 'admin@example.com',
		password: 'd1r3ctu5',
	},
	{
		refresh: {
			auto: true,
		},
	}
);

You can also set how much time before the expiration you want to auto-refresh the token.

await directus.auth.login(
	{
		email: 'admin@example.com',
		password: 'd1r3ctu5',
	},
	{
		refresh: {
			auto: true,
			time: 30000, // refesh the token 30 secs before the expiration
		},
	}
);

# Refresh Auth Token

You can manually refresh the authentication token.

await directus.auth.refresh();

An optional parameter will accept auto-refresh information.

await directus.auth.refresh({
	auto: true,
	time: 30000, // refesh the token 30 secs before the expiration
});

# Logout

await directus.auth.logout();

# Request a Password Reset

await directus.auth.password.request('admin@example.com');

# Reset a Password

await directus.auth.password.reset('abc.def.ghi', 'n3w-p455w0rd');

Note: The token passed in the first parameter is sent in an email to the user when using request()

# Transport

The transport object abstracts how you communicate with Directus. Transports can be customized to use different HTTP libraries for example.

# Interface

// Simplified version, `import { ITransport } from '@directus/sdk';`
interface ITransport {
	url;
	get(path);
	head(path);
	options(path);
	delete(path, data = undefined);
	post(path, data);
	put(path, data);
	patch(path, data);
}

# AxiosTransport

The default transport used in both browser and node deployments.

# Options

AxiosTransport requires a base URL and a storage implementation to work.

const transport = new AxiosTransport('http://example.com', new MemoryStorage());
await transport.get('/server/info');

# Storage

The storage is used to load and save SDK data.

# LocalStorage

The storage used in environments where Local Storage is supported.

# Options

The LocalStorage implementation accepts a transparent prefix. Use this when you need multiple SDK instances with independent authentication for example.

# MemoryStorage

The storage used when SDK data is ephemeral. For example: only during the lifecycle of the process.

# Options

The MemoryStorage implementation accepts a transparent prefix so you can have multiple instances of the SDK without having clashing keys.

# Collections

directus.collections;

Same methods as directus.items("directus_collections").

# Fields

directus.fields;

Same methods as directus.items("directus_fields").

# Files

directus.files;

Same methods as directus.items("directus_files").

# Folders

directus.folders;

Same methods as directus.items("directus_folders").

# Permissions

directus.permissions;

Same methods as directus.items("directus_permissions").

# Presets

directus.presets;

Same methods as directus.items("directus_presets").

# Relations

directus.relations;

Same methods as directus.items("directus_relations").

# Revisions

directus.revisions;

Same methods as directus.items("directus_revisions").

# Roles

directus.roles;

Same methods as directus.items("directus_roles").

# Settings

directus.settings;

Same methods as directus.items("directus_settings").

# Server

# Ping the Server

await directus.server.ping();

# Get Server/Project Info

await directus.server.info();

# Users

directus.users;

Same methods as directus.items("directus_users"), and:

# Invite a New User

await directus.users.invites.send('admin@example.com', 'fe38136e-52f7-4622-8498-112b8a32a1e2');

The second parameter is the role of the user

# Accept a User Invite

await directus.users.invites.accept('<accept-token>', 'n3w-p455w0rd');

The provided token is sent to the user's email

# Enable Two-Factor Authentication

await directus.users.tfa.enable('my-password');

# Disable Two-Factor Authentication

await directus.users.tfa.disable('691402');

# Get the Current User

await directus.users.me.read();

Supports optional query:

await directus.users.me.read({
	fields: ['last_access'],
});

# Update the Current Users

await directus.users.me.update({ first_name: 'Admin' });

Supports optional query:

await directus.users.me.update({ first_name: 'Admin' }, { fields: ['last_access'] });

# Utils

# Get a Random String

await directus.utils.random.string();

Supports an optional length (defaults to 32):

await directus.utils.random.string(50);

# Generate a Hash for a Given Value

await directus.utils.hash.generate('My String');

# Verify if a Hash is Valid

await directus.utils.hash.verify('My String', '$argon2i$v=19$m=4096,t=3,p=1$A5uogJh');

# Sort Items in a Collection

await directus.utils.sort('articles', 15, 42);

This will move item 15 to the position of item 42, and move everything in between one "slot" up.

# Revert to a Previous Revision

await directus.utils.revert(451);

Note: The key passed is the primary key of the revision you'd like to apply.


# TypeScript

If you are using TypeScript, the JS-SDK requires TypeScript 3.8 or newer. TypeScript will also improve the development experience by providing relevant information when manipulating your data. For example, directus.items knows about your collection types if you feed the SDK with enough information in the construction of the SDK instance. This allows for a more detailed IDE suggestions for return types, sorting, and filtering.

type BlogPost = {
	id: ID;
	title: string;
};

type BlogSettings = {
	display_promotions: boolean;
};

type MyCollections = {
	posts: BlogPost;
	settings: BlogSettings;
};

// This is how you feed custom type information to Directus.
const directus = new Directus<MyCollections>('http://url');

// ...

const post = await directus.items('posts').readOne(1);
// typeof(post) is a partial BlogPost object

const settings = await posts.singleton('settings').read();
// typeof(settings) is a partial BlogSettings object

You can also extend the Directus system type information by providing type information for system collections as well.

import { Directus } from '@directus/sdk';

// Custom fields added to Directus user collection.
type UserType = {
	level: number;
	experience: number;
};

type CustomTypes = {
	/*
	This type will be merged with Directus user type.
	It's important that the naming matches a directus
	collection name exactly. Typos won't get caught here
	since SDK will assume it's a custom user collection.
	*/
	directus_users: UserType;
};

const directus = new Directus<CustomTypes>('https://api.example.com');

await directus.auth.login({
	email: 'admin@example.com',
	password: 'password',
});

const me = await directus.users.me.read();
// typeof me = partial DirectusUser & UserType;

// OK
me.level = 42;

// Error TS2322: Type "string" is not assignable to type "number".
me.experience = 'high';