Directus
Flows
All flows have data from the following items
$trigger- Each operation’s id
To access it, you can use mustache:
"{{ $trigger.body.name }}"
Or for scripts, use data
data.$trigger.body.name
Example JSON
{
"$trigger": {
"path": "/trigger/3ba54f5a-5525-4bd0-8cd8-df4b143f08e5",
"query": {},
"body": {
"name": "ty",
"unique_count": 1,
"search_count": 1
},
"method": "POST",
"headers": {
"host": "hostname",
"user-agent": "my_agent/2023.2.2",
"content-length": "57",
"accept": "*/*",
"accept-encoding": "gzip",
"authorization": "Bearer token",
"cdn-loop": "cloudflare",
"cf-connecting-ip": "ip_addr",
"cf-ipcountry": "US",
"cf-ray": "6e55ed5c5a2306a7-NND",
"cf-visitor": "{\"scheme\":\"https\"}",
"content-type": "application/json",
"x-forwarded-for": "ip_addr",
"x-forwarded-host": "hostname",
"x-forwarded-proto": "https"
}
},
"$last": [
"ty"
],
"$accountability": {
"user": "569eae4a-f905-4fdf-bdfc-35bb8db31852",
"role": "d779759d-d4cc-40f3-912a-a17a4e83f015",
"admin": true,
"app": true,
"ip": "ip_addr",
"userAgent": "agent/2023.2.2",
"permissions": []
},
"$env": {},
"query_id": [
{
"name": "user",
"date_updated": "2023-07-12T02:41:24.719Z",
"config": null
}
],
"item_update_joye2": [
"user"
]
}
Remove older then 5 years
{
"filter": {
"initiationtimestamp": {
"_lt": "$NOW(-5 years)"
}
}
}
Read Database
When using the read database operation, it will return an array.
data is the flow object. So anything in there can be retrieved from.
For updating the database (or anything with Payload), make sure to edit the payload in raw form only, and then insert the variable name.
"{{data_variable}}"
If you save and re-enter and it has it escaped, you need to remove and do it again in the raw mode.
Queries
The query is effectively the search query, but in JSON. query - filter rules
[aggregate][count]=id
{
"aggregate": {
"count": "id"
}
}
To do multiple values:
{
"aggregate": {
"count": [
"id",
"name2"
]
}
}
Run Script
This example checks the data from a read operation, see’s if it is 1 for that field, and then increments it if true.
Example:
module.exports = async function(data) {
let unique_count = data.read_ahc_data[0].unique_count;
let search_count = data.read_ahc_data[0].search_count;
if(data.$trigger.body.unique_count === 1) {
unique_count += 1
}
if(data.$trigger.body.search_count === 1) {
search_count += 1
}
return {
name: data.$trigger.body.name,
unique_count: unique_count,
search_count: search_count
};
}
Aggregation
You can aggregate with the aggregate query
For example, to count the number of id records
https://directus.dev.lan/items/users?aggregate[count]=id
Custom Extension
Docker Structure for endpoint /login
drwxr-xr-x 1000:1000 296 MB ├── /directus
-rwxr-xr-x 1000:1000 437 B │ ├── cli.js
drwxr-xr-x 1000:1000 0 B │ ├── database
drwxr-xr-x 1000:1000 77 B │ ├── extensions
drwxr-xr-x 0:0 77 B │ │ └── endpoints
drwxr-xr-x 0:0 77 B │ │ └── login
-rw-r--r-- 0:0 77 B │ │ └── index.js
To create a new extension
npm init directus-extension
vi new_extension/src/index.js
// index.js
export default (router) => {
router.get('/', (req, res) => res.send('Hello, World!'));
};
Querying with JSON
It can use JSON, but you have to specify each section (instead of one gigantic query operator (which may not exist))
filter={ "initiationmethod": { "_eq": "INBOUND" }}
aggregate={ "count": "id" }
fields=id
Probably this page for each top level can be included
So a query like this would work
domain/items/aggregate={ "count": "id" }&filter={ "initiationmethod": { "_eq": "INBOUND" }}
Extension
Endpoint
export default defineEndpoint((router, context) => {
const { services, getSchema } = context;
const { ItemsService } = services;
router.get('/', async (req, res) => {
}
## Hook
Action
create
export default ({ action }, { env, services }) => {
const { MailService, ItemsService } = services;
action('mycollection.items.create', async ({ key, collection, payload }, { schema }) => {
}
}
Filter
create
export default ({ filter }, { env }) => {
filter('items.create', async (input, { collection }) => {
}
}
update
export default ({ filtjj/filterer }, { }
delete
filter(`${COLLECTION}.items.delete`, async ( keys , meta, obj3, obj4) => {
readQuery
const roles = await rolesService.readByQuery({
fields: ['id', 'name'],
filter: { name: { _eq: name } }
})
if(roles.length !== 1) {
throw new Error("Can't be more than 1 role for the specified name, or it's missing")
}
return roles[0]
Emails
MailService uses NodeMailer to work. Nodemailer send config
This passes everything directly to nodemailer’s sendMail
await mailService.send({})
Icons
To use icons, you can use this library
HTTP Query fields and filtering
Fields
This will get all items and their sub items. Not optimized. You can also get item.subitem (like user.policy.id)
fields=*.*,item.subitem
Filter Only show items of contact not null
filter[contact][_nnull]
You can also combine them with OR or AND statement
filter[_or][1][contact][_null]
filter[_or][1][email_address][_null]