开发框架SDK JS SDK

JS SDK 在 JavaScript 支持的项目(浏览器和 Node.js)中为 Directus API 提供了一个直观的界面。 默认实现使用 [Axios](https://npmjs.com/axios) 进行传输,使用 localStorage 存储状态。

Installation

bash
npm install @directus/sdk

Basic Usage

这是使用 JS SDK 的起点。 创建 Directus 实例后,您可以开始从中调用方法来访问您的项目和数据。

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

const directus = new Directus('http://directus.example.com')

您始终可以访问 公共角色 可用的数据.

js
async function publicData() {
  // GET DATA

  // 我们不需要验证 public 角色是否可以访问 some_public_collection。
  const publicData = await directus.items('some_public_collection').readByQuery({ sort: ['id'] })

  console.log(publicData.data)
}

Basic Authentication

要访问 公共角色 无法访问的任何内容,您必须经过 认证

js
async function start() {
  // 验证

  let authenticated = false

  // 如果存在,尝试使用令牌进行身份验证
  await directus.auth
    .refresh()
    .then(() => {
      authenticated = true
    })
    .catch(() => {})

  // 让我们登录以防我们没有令牌或者它无效/过期
  while (!authenticated) {
    const email = window.prompt('Email:')
    const password = window.prompt('Password:')

    await directus.auth
      .login({ email, password })
      .then(() => {
        authenticated = true
      })
      .catch(() => {
        window.alert('Invalid credentials')
      })
  }

  // 获取数据

  // 身份验证后,我们可以从用户有权访问的任何集合中获取数据。
  const privateData = await directus.items('some_private_collection').readByQuery({ sort: ['id'] })

  console.log(publicData.data)
}

start()

Custom Configuration

上一节介绍了 JS SDK 的基本安装和使用,以及 init 的默认配置。 但有时您可能需要自定义这些默认值。

Constructor

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

const directus = new Directus(url, init)

Parameters


url required

  • TypeString
  • Description — 指向您的 Directus 实例的字符串。 例如, https://example.directus.io
  • Default — N/A

init optional

  • TypeObject
  • Description — 定义身份验证、存储和传输设置。
  • Default — 下面显示了 init 的默认值。
js
// 这是默认的初始化对象
const config = {
  auth: {
    mode: 'cookie', // 'json' in Node.js
    autoRefresh: true,
    msRefreshBeforeExpires: 30000,
    staticToken: '',
  },
  storage: {
    prefix: '',
    mode: 'LocalStorage', // 'MemoryStorage' in Node.js
  },
  transport: {
    params: {},
    headers: {},
    onUploadProgress: (ProgressEvent) => {},
    maxBodyLength: null,
    maxContentLength: null,
  },
}

Customize auth

定义 SDK 如何处理身份验证。 默认情况下,Directus 创建一个自动处理刷新令牌的 auth 实例。

js
const auth = {
  mode: 'cookie', // 'json' in Node.js
  autoRefresh: true,
  msRefreshBeforeExpires: 30000,
  staticToken: '',
}

Options

mode

  • TypeString
  • Description — 定义您要用于身份验证的模式。 它可以是用于 cookie 的 'cookie' 或用于 JWT 的 'json'
  • Default — 在浏览器上默认为cookie,否则默认为json

我们建议尽可能使用 cookie 来防止任何类型的攻击,主要是 XSS。

autoRefresh

  • TypeBoolean
  • Description — 确定 SDK 是否自动处理刷新令牌。
  • Default — 默认是:true.

msRefreshBeforeExpires

  • TypeNumber
  • Description —当启用autoRefresh时,这会告诉刷新令牌过期和需要刷新之前的毫秒数。
  • Default — 默认是:30000.

staticToken

  • TypeString
  • Description - 定义要使用的静态令牌。 它与上述选项不兼容,因为它不刷新。
  • Default — 默认是:'' (no static token).

Extend auth

可以通过扩展 IAuth 来提供自定义实现。 虽然这在某些高级情况下可能很有用,但对于大多数用例来说并不需要。

js
import { Directus, IAuth } from '@directus/sdk'

class MyAuth extends IAuth {
  async login() {
    return { access_token: '', expires: 0 }
  }

  async logout() {}
  async refresh() {
    return { access_token: '', expires: 0 }
  }

  async static() {
    return true
  }
}

const directus = new Directus('https://example.directus.app', {
  auth: new MyAuth(),
})

Customize storage

存储用于加载和保存令牌信息。 默认情况下,Directus 创建一个自动处理存储信息的 storage 实例。

js
const storage = {
  prefix: '',
  mode: 'LocalStorage', // 'MemoryStorage' in Node.js
}

多个实例
如果您想使用 SDK 的多个实例,您应该为每个实例设置不同的 prefix

axios 实例可用于自定义请求,方法是调用:

ts
await directus.transport.<method>('/path/to/endpoint', {
 /* body, params, ... */
});

Options


prefix

  • TypeString
  • Description — 定义保存的令牌前缀令牌。 当使用多个 SDK 实例时,这应该用不同的值来实现。
  • Default — 默认是:'' (no prefix).

mode

  • TypeString
  • Description — 定义用于保存令牌的存储位置。 允许的值为LocalStorageMemoryStorageLocalStorage 模式与 Node.js 不兼容。 MemoryStorage 不是永久性的,所以一旦离开选项卡或退出进程,您将需要再次进行身份验证。
  • Default — 在浏览器上默认为LocalStorage,在 Node.js 上默认为MemoryStorage

Extend storage

可以通过扩展 BaseStorage 来提供自定义实现。 虽然这在某些高级情况下可能很有用,但对于大多数用例来说并不需要。

js
import { BaseStorage, Directus } from '@directus/sdk'

class SessionStorage extends BaseStorage {
  get(key) {
    return sessionStorage.getItem(key)
  }

  set(key, value) {
    return sessionStorage.setItem(key, value)
  }

  delete(key) {
    return sessionStorage.removeItem(key)
  }
}

const directus = new Directus('https://example.directus.app', {
  storage: new SessionStorage(),
})

Customize transport

定义要自定义的有关 Transport 的设置。

默认情况下,Directus 创建一个自动处理请求的 Transport 实例。 它使用 axios,因此它在浏览器和 Node.js 中都兼容。 使用 axios,还可以处理上传进度(fetch 的缺点)。

init.transport 中的配置被传递给 axios。 更多详细信息,请参见axios文档中的Request Config

js
export default {
  params: {},
  headers: {},
  onUploadProgress: (ProgressEvent) => {},
  maxBodyLength: null,
  maxContentLength: null,
}

Options


params

  • TypeObject
  • Description — 定义一个对象,其中包含要作为附加查询字符串传递的键和值。
  • Default — N/A

headers

  • TypeObject
  • Description - 定义一个对象,其中包含要作为附加标头传递的键和值。
  • Default — N/A

onUploadProgress

  • TypeFunction
  • Description — 定义一个回调函数来指示上传进度。
  • Default — N/A

ProgressEvent 请参阅 MDN 文档以了解有关ProgressEvent.


maxBodyLength

  • TypeNumber
  • Description — 以字节为单位的最大正文长度。 设置 Infinity 表示没有限制。
  • Default — N/A

maxContentLength

  • TypeNumber
  • Description — 以字节为单位的最大内容长度。 设置 Infinity 表示没有限制。
  • Default — N/A

Extend Transport

可以通过扩展“ITransport”来提供自定义实现。 例如,您可以自定义它以使用不同的 HTTP 库。 虽然这在某些高级情况下可能很有用,但对于大多数用例来说并不需要。

js
import { Directus, ITransport } from '@directus/sdk'

class MyTransport extends ITransport {
  buildResponse() {
    return {
      raw: '',
      data: {},
      status: 0,
      headers: {},
    }
  }

  async get(path, options) {
    return this.buildResponse()
  }

  async head(path, options) {
    return this.buildResponse()
  }

  async options(path, options) {
    return this.buildResponse()
  }

  async delete(path, data, options) {
    return this.buildResponse()
  }

  async post(path, data, options) {
    return this.buildResponse()
  }

  async put(path, data, options) {
    return this.buildResponse()
  }

  async patch(path, data, options) {
    return this.buildResponse()
  }
}

const directus = new Directus('https://example.directus.app', {
  transport: new MyTransport(),
})

TypeScript

Version >= 4.1

虽然不是必需的,但建议使用 TypeScript 以获得轻松的开发体验。 这允许对返回类型、排序、过滤等提供更详细的 IDE 建议。

要为 SDK 提供当前架构,您需要将其传递给构造函数。

ts
interface BlogPost {
  id: ID
  title: string
}

interface BlogSettings {
  display_promotions: boolean
}

interface MyCollections {
  posts: BlogPost
  settings: BlogSettings
}

// 这就是您向 Directus 提供自定义类型信息的方式。
const directus = new Directus<MyCollections>('https://example.directus.app')

// ...

const post = await directus.items('posts').readOne(1)
// typeof(post) 是部分 BlogPost 对象

const settings = await posts.singleton('settings').read()
// typeof(settings) 是部分 BlogSettings 对象

您还可以通过为系统集合提供类型信息来扩展 Directus 系统类型信息。

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

// 添加到 Directus 用户集合的自定义字段。
interface UserType {
  level: number
  experience: number
}

interface CustomTypes {
  /*
 此类型将与 Directus 用户类型合并。 命名与 directus 集合名称完全匹配很重要。 在这里不会发现拼写错误,因为 SDK 会假定它是自定义用户集合。
 */
  directus_users: UserType
}

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

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

// 错误 TS2322:类型“字符串”不可分配给类型“数字”。
me.experience = 'high'

Authentication

Get current token

ts
const token = await directus.auth.token

异步
读取令牌是一个异步获取器。 这确保在返回当前令牌之前等待任何当前活动的refresh调用。

Login

With credentials

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

With static tokens

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

Refresh Auth Token

默认情况下,Directus 将处理令牌刷新。 不过,您可以通过将 autoRefresh 设置为 false 来手动处理此行为。

js
await directus.auth.refresh()

本地开发
如果您在本地进行开发,您可能无法在所有浏览器中自动刷新您的身份验证令牌。 这是因为默认的身份验证配置需要设置安全 cookie,并且并非所有浏览器都允许本地主机这样做。 您可以使用支持此功能的浏览器,例如 Firefox,或 禁用安全 cookie

Logout

js
await directus.auth.logout()

Request a Password Reset

默认情况下,在 .env 文件的 PUBLIC_URL 中定义的地址用于链接到发送的重置密码页面 电子邮件:

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

但是自定义地址可以作为第二个参数传递:

js
await directus.auth.password.request(
  'admin@example.com',
  'https://myapp.com' // In this case, the link will be https://myapp.com?token=FEE0A...
)

Note: 要使用自定义地址,您需要配置 PASSWORD_RESET_URL_ALLOW_LIST 环境变量 以启用此功能。

Reset a Password

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

注意:在第一个参数中传递的令牌在使用 request() 时通过电子邮件发送给用户

Items

您可以通过向 items 函数提供集合(和类型,在 TypeScript 的情况下)来获取项目处理程序的实例。 以下示例将使用Article类型。

JavaScript

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

const directus = new Directus('https://example.directus.app')

const articles = directus.items('articles')

TypeScript

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

// 根据其字段映射您的集合结构。
interface Article {
  id: ID
  title: string
  body: string
  published: boolean
}

// 将您的集合映射到其各自的类型。 SDK 稍后会根据使用情况推断其类型。
interface MyBlog {
  // [collection_name]: typescript_type
  articles: Article

  // 您还可以扩展 Directus 集合。 命名必须与 Directus 系统集合相匹配,它将被合并到系统规范中。
  directus_users: {
    bio: string
  }
}

// 让 SDK 了解您的集合类型。
const directus = new Directus<MyBlog>('https://example.directus.app')

// typeof(article) 是部分“文章”
const article = await directus.items('articles').readOne(10)

// 错误 TS2322:“hello”不可分配给类型“boolean”。
// post.published = 'hello';

Create Single Item

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

Create Multiple Items

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

Read By Query

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

Read All

js
await articles.readByQuery({
  // 默认情况下,API 将结果限制为 100。
  // 设置为-1,会返回所有结果,但是对于大的结果集可能会导致性能下降。
  limit: -1,
})

Read Single Item

js
await articles.readOne(15)

支持可选查询:

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

Read Multiple Items

js
await articles.readMany([15, 16, 17])

支持可选查询:

js
await articles.readMany([15, 16, 17], {
  fields: ['title'],
})

Update Single Item

js
await articles.updateOne(15, {
  title: 'This articles now has a different title',
})

支持可选查询:

js
await articles.updateOne(
  42,
  {
    title: 'This articles now has a similar title',
  },
  {
    fields: ['title'],
  }
)

Update Multiple Items

js
await articles.updateMany([15, 42], {
  title: 'Both articles now have the same title',
})

支持可选查询:

js
await articles.updateMany(
  [15, 42],
  {
    title: 'Both articles now have the same title',
  },
  {
    fields: ['title'],
  }
)

Delete

js
// One
await articles.deleteOne(15)

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

Request Parameter Overrides

要覆盖任何 axios 请求参数,请提供带有 requestOptions 对象的附加参数:

js
await articles.createOne(
  { title: 'example' },
  { fields: ['id'] },
  {
    requestOptions: {
      headers: {
        'X-My-Custom-Header': 'example',
      },
    },
  }
)

Activity

js
directus.activity

directus.items("directus_activity")相同的方法.

Comments

js
directus.comments

directus.items("directus_comments")相同的方法.

Collections

js
directus.collections

directus.items("directus_collections")相同的方法.

Fields

js
directus.fields

directus.items("directus_fields")相同的方法.

Files

js
directus.files

directus.items("directus_files")相同的方法.

Uploading a file

要上传文件,您需要发送一个 multipart/form-data 作为正文。 在浏览器端你这样做:

js
/* index.js */
import { Directus } from 'https://unpkg.com/@directus/sdk@latest/dist/sdk.esm.min.js'

const directus = new Directus('https://example.directus.app', {
  auth: {
    staticToken: 'STATIC_TOKEN', // 如果您想使用静态令牌,请在下方查看如何使用电子邮件和密码。
  },
})

// await directus.auth.login({ email, password }) 如果要使用邮箱和密码,去掉上面的staticToken。

const form = document.querySelector('#upload-file')

if (form && form instanceof HTMLFormElement) {
  form.addEventListener('submit', async (event) => {
    event.preventDefault()

    const form = new FormData(event.target)
    await directus.files.createOne(form)
  })
}
html
<!-- index.html -->
<head></head>
<body>
 <form id="upload-file">
  <input type="text" name="title" />
  <input type="file" name="file" />
     <button>Send</button>
 </form>
 <script src="/index.js" type="module"></script>
</body>
</html>

NodeJS usage

从 NodeJS 环境上传文件时,您必须覆盖标头以确保设置正确的边界:

js
import { Directus } from 'https://unpkg.com/@directus/sdk@latest/dist/sdk.esm.min.js';

const directus = new Directus('https://example.directus.app', {
 auth: {
  staticToken: 'STATIC_TOKEN', // 如果您想使用静态令牌,请在下方查看如何使用电子邮件和密码。
 },
});

const form = new FormData();
form.append("file", fs.createReadStream("./to_upload.jpeg"));

const fileId = await directus.files.createOne(form, {}, {
  requestOptions: {
    headers: {
      ...form.getHeaders()
    }
  }
);

Importing a file

Example of importing a file from a URL:

js
await directus.files.import({
  url: 'http://www.example.com/example-image.jpg',
})

使用自定义数据导入文件的示例:

js
await directus.files.import({
  url: 'http://www.example.com/example-image.jpg',
  data: {
    title: 'My Custom File',
  },
})

Folders

js
directus.folders

directus.items("directus_folders")相同的方法。

Permissions

js
directus.permissions

directus.items("directus_permissions")相同的方法。

Presets

js
directus.presets

directus.items("directus_presets")相同的方法。

Relations

js
directus.relations

directus.items("directus_relations")相同的方法。

Revisions

js
directus.revisions

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

Roles

js
directus.roles

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

Settings

js
directus.settings

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

Server

Ping the Server

js
await directus.server.ping()

Get Server/Project Info

js
await directus.server.info()

Users

js
directus.users

directus.items("directus_users")相同的方法, and:

Invite a New User

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

第二个参数是用户的角色

Accept a User Invite

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

提供的令牌被发送到用户的电子邮件

Enable Two-Factor Authentication

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

Disable Two-Factor Authentication

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

Get the Current User

js
await directus.users.me.read()

支持可选查询:

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

Update the Current Users

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

支持可选查询:

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

Utils

Get a Random String

js
await directus.utils.random.string()

支持可选的“长度”(默认为 32):

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

Generate a Hash for a Given Value

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

Verify if a Hash is Valid

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

Sort Items in a Collection

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

这会将项目“15”移动到项目“42”的位置,并将一个“槽”之间的所有内容向上移动。

Revert to a Previous Revision

js
await directus.utils.revert(451)

注意:传递的键是您要应用的修订的主键。