Skip to content
On this page

App Extension Composables โ€‹

There are several composables available as part of the Directus Extensions SDK that make working with Directus easier.

Rather than needing to rewrite logic from scratch, extension developers can leverage primitives like useApi() or useStores(), to handle common complexities when building extensions.

useApi() โ€‹

The useApi composable is a wrapper around the axios library that adds the Authorization header and provides concurrency control when making multiple requests.

Use the useApi composable when you need to make authorized API requests from your App extension.

html
<script setup>
import { useApi } from '@directus/extensions-sdk';

const api = useApi();

async function fetchData() {
    const response = await api.get('ENDPOINT_URL');
    data.value = response.data;
};
fetchData();
</script>
<script setup>
import { useApi } from '@directus/extensions-sdk';

const api = useApi();

async function fetchData() {
    const response = await api.get('ENDPOINT_URL');
    data.value = response.data;
};
fetchData();
</script>

useStores() โ€‹

useStores serves as the primary way for App extensions to interact with data and features within a Directus instance.

Within useStores are stores like the usePermissionsStore, useCollectionsStore and useFieldsStore among others.

html
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { useFieldsStore, usePermissionsStore, useCollectionStore } = useStores();

const fieldsStore = useFieldsStore();
const permissionsStore = usePermissionsStore();
const collectionStore = useCollectionStore();
</script>
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { useFieldsStore, usePermissionsStore, useCollectionStore } = useStores();

const fieldsStore = useFieldsStore();
const permissionsStore = usePermissionsStore();
const collectionStore = useCollectionStore();
</script>

useFieldsStore() โ€‹

The useFieldsStore is used to access and modify collections and fields.

Use this store when you need to:

  • retrieve information about a collection's field
  • perform mutations on a collection's field such as create, update, upsert, or delete
  • retrieve translations for collection's field (useful for internationalization)
html
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { useFieldsStore } = useStores();
const fieldsStore = useFieldsStore();

// create a field
const newField = await fieldStore.createField('collection_key', {
  name: 'title',
});

// update a field
const updatedField = await fieldStore.updateField(
  'collection_key',
  'field_key',
  {
    name: 'new title',
  }
);
</script>
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { useFieldsStore } = useStores();
const fieldsStore = useFieldsStore();

// create a field
const newField = await fieldStore.createField('collection_key', {
  name: 'title',
});

// update a field
const updatedField = await fieldStore.updateField(
  'collection_key',
  'field_key',
  {
    name: 'new title',
  }
);
</script>

For a deep dive on how to use the useFieldsStore composable, see the implementation in our codebase.

usePermissionsStore() โ€‹

The usePermissionsStore is used to check for access control before performing operations within your App extension.

html
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { usePermissionsStore } = useStores();
const permissionsStore = usePermissionsStore();

// check if user can create a collection
const canCreate = permissionsStore.hasPermission('collection_name', 'create');

// check if user can read a collection
const canRead = permissionsStore.hasPermission('collection_name', 'read');
</script>
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { usePermissionsStore } = useStores();
const permissionsStore = usePermissionsStore();

// check if user can create a collection
const canCreate = permissionsStore.hasPermission('collection_name', 'create');

// check if user can read a collection
const canRead = permissionsStore.hasPermission('collection_name', 'read');
</script>

For a deep dive on how to use the usePermissionsStore composable, see the implementation in our codebase.

useCollectionsStore() โ€‹

useCollectionsStore provides access to collections directly from your App extension.

Use this store when you need to:

  • perform CRUD operations on a collection such as create, update, upsert, or delete
  • retrieve translations for a collection (useful for internationalization)
  • retrieve all collections or visible collections within a Directus instance
html
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { useCollectionsStore } = useStores();
const collectionsStore = useCollectionsStore();

// get all collections
collectionsStore.collections.value;

// get all visible collections
collectionsStore.visibleCollections.value;

// get a collection
collectionStore.getCollection("collection_key");

// delete a collection
await collectionStore.deleteCollection("collection_key");

// upsert (create or update) a collection
await collectionStore.upsertCollection("collection_key", {...});
</script>
<script setup>
import { useStores } from '@directus/extensions-sdk';

const { useCollectionsStore } = useStores();
const collectionsStore = useCollectionsStore();

// get all collections
collectionsStore.collections.value;

// get all visible collections
collectionsStore.visibleCollections.value;

// get a collection
collectionStore.getCollection("collection_key");

// delete a collection
await collectionStore.deleteCollection("collection_key");

// upsert (create or update) a collection
await collectionStore.upsertCollection("collection_key", {...});
</script>

For a deep dive on how to use the useCollectionsStore composable, see the implementation in our codebase.

Explore all Stores within useStores

While useFieldsStore, usePermissionsStore and useCollectionsStore cover the common scenarios, the useStore composable contains additional sub-stores. Reference the full list in of sub-stores in our codebase.

useCollection() โ€‹

Theย useCollectionย composable provides access to metadata about collections (such as name, fields, type, icon).

Use useCollection composable when you need to retrieve:

  • metadata about a collection (such as name, type, icon)
  • fields within a collection and their default values
  • the primary key and user created field
  • accountability scope
html
<script setup>
import { useCollection } from '@directus/extensions-sdk';
const { info, fields, defaults, primaryKeyField } = useCollection('collection_name');

info.value;
// => [{ name: 'collection_name', icon: 'box', type: 'table', ... }]

fields.value;
// => [{ name: 'title', type: 'string', ... }]

defaults.value;
// => { title: 'default_value' }

primaryKeyField.value;
// => { name: 'id', type: 'uuid', ... }
</script>
<script setup>
import { useCollection } from '@directus/extensions-sdk';
const { info, fields, defaults, primaryKeyField } = useCollection('collection_name');

info.value;
// => [{ name: 'collection_name', icon: 'box', type: 'table', ... }]

fields.value;
// => [{ name: 'title', type: 'string', ... }]

defaults.value;
// => { title: 'default_value' }

primaryKeyField.value;
// => { name: 'id', type: 'uuid', ... }
</script>

useCollection vs useCollectionStore

For full capabilities like retrieving, updating and deleting collection items, use the useCollectionStoreย composable instead.

For a deep dive on how to use the useCollection composable, see the implementation in our codebase.

useItems() โ€‹

The useItems composable is used to retrieve items in a collection and provides pagination features.

Fetching items in a collection โ€‹

html
<script setup>
import { useItems } from '@directus/extensions-sdk';

const collectionRef = ref('collection_key');

const query = {
		fields: ref(['*']),
		limit: ref(1),
		sort: ref(null),
		search: ref(null),
		filter: ref(null),
		page: ref(1),
	}

const { getItems, items } = useItems(collectionRef, query);

query.search.value = 'search_value' // update query search

query.limit.value = 10 // update query limit

await getItems(); // fetch the items

const data = items.value; // read the items
</script>
<script setup>
import { useItems } from '@directus/extensions-sdk';

const collectionRef = ref('collection_key');

const query = {
		fields: ref(['*']),
		limit: ref(1),
		sort: ref(null),
		search: ref(null),
		filter: ref(null),
		page: ref(1),
	}

const { getItems, items } = useItems(collectionRef, query);

query.search.value = 'search_value' // update query search

query.limit.value = 10 // update query limit

await getItems(); // fetch the items

const data = items.value; // read the items
</script>

Fetching the item and page count โ€‹

html
<script setup>
import { useItems } from '@directus/extensions-sdk';

const collectionRef = ref('collection_key')

const { getItemCount, itemCount, totalPages } = useItems(collectionRef);

await getItemCount(); // fetch the item count

const data = itemCount.value; // read the item count

const pages = totalPages.value; // read the total pages
</script>
<script setup>
import { useItems } from '@directus/extensions-sdk';

const collectionRef = ref('collection_key')

const { getItemCount, itemCount, totalPages } = useItems(collectionRef);

await getItemCount(); // fetch the item count

const data = itemCount.value; // read the item count

const pages = totalPages.value; // read the total pages
</script>

Fetching the total count โ€‹

html
<script setup>
import { useItems } from '@directus/extensions-sdk';

const collectionRef = ref('collection_key')

const { getTotalCount, totalCount } = useItems(collectionRef);

await getTotalCount(); // fetch the total item count

const data = totalCount.value; // read the total item count
</script>
<script setup>
import { useItems } from '@directus/extensions-sdk';

const collectionRef = ref('collection_key')

const { getTotalCount, totalCount } = useItems(collectionRef);

await getTotalCount(); // fetch the total item count

const data = totalCount.value; // read the total item count
</script>

For a deep dive on how to use the useItems() composable, see the implementation in our codebase.

Explore all Composables

While these core composables cover many common use cases, for a complete reference of all available Extension SDK composables within Directus, check out our GitHub repository.