@directus/api 30.0.0 → 31.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +5 -0
- package/dist/auth/drivers/oauth2.js +17 -3
- package/dist/auth/drivers/openid.js +17 -3
- package/dist/controllers/mcp.d.ts +2 -0
- package/dist/controllers/mcp.js +33 -0
- package/dist/controllers/users.js +17 -7
- package/dist/controllers/versions.js +3 -2
- package/dist/database/errors/dialects/mssql.d.ts +1 -1
- package/dist/database/errors/dialects/mssql.js +18 -10
- package/dist/database/migrations/20250813A-add-mcp.d.ts +3 -0
- package/dist/database/migrations/20250813A-add-mcp.js +18 -0
- package/dist/database/run-ast/README.md +46 -0
- package/dist/mcp/define.d.ts +2 -0
- package/dist/mcp/define.js +3 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/schema.d.ts +485 -0
- package/dist/mcp/schema.js +219 -0
- package/dist/mcp/server.d.ts +97 -0
- package/dist/mcp/server.js +310 -0
- package/dist/mcp/tools/assets.d.ts +3 -0
- package/dist/mcp/tools/assets.js +54 -0
- package/dist/mcp/tools/collections.d.ts +84 -0
- package/dist/mcp/tools/collections.js +90 -0
- package/dist/mcp/tools/fields.d.ts +101 -0
- package/dist/mcp/tools/fields.js +157 -0
- package/dist/mcp/tools/files.d.ts +235 -0
- package/dist/mcp/tools/files.js +103 -0
- package/dist/mcp/tools/flows.d.ts +323 -0
- package/dist/mcp/tools/flows.js +85 -0
- package/dist/mcp/tools/folders.d.ts +95 -0
- package/dist/mcp/tools/folders.js +96 -0
- package/dist/mcp/tools/index.d.ts +15 -0
- package/dist/mcp/tools/index.js +29 -0
- package/dist/mcp/tools/items.d.ts +87 -0
- package/dist/mcp/tools/items.js +141 -0
- package/dist/mcp/tools/operations.d.ts +171 -0
- package/dist/mcp/tools/operations.js +77 -0
- package/dist/mcp/tools/prompts/assets.md +8 -0
- package/dist/mcp/tools/prompts/collections.md +336 -0
- package/dist/mcp/tools/prompts/fields.md +521 -0
- package/dist/mcp/tools/prompts/files.md +180 -0
- package/dist/mcp/tools/prompts/flows.md +495 -0
- package/dist/mcp/tools/prompts/folders.md +34 -0
- package/dist/mcp/tools/prompts/index.d.ts +16 -0
- package/dist/mcp/tools/prompts/index.js +19 -0
- package/dist/mcp/tools/prompts/items.md +317 -0
- package/dist/mcp/tools/prompts/operations.md +721 -0
- package/dist/mcp/tools/prompts/relations.md +386 -0
- package/dist/mcp/tools/prompts/schema.md +130 -0
- package/dist/mcp/tools/prompts/system-prompt-description.md +1 -0
- package/dist/mcp/tools/prompts/system-prompt.md +44 -0
- package/dist/mcp/tools/prompts/trigger-flow.md +214 -0
- package/dist/mcp/tools/relations.d.ts +73 -0
- package/dist/mcp/tools/relations.js +93 -0
- package/dist/mcp/tools/schema.d.ts +54 -0
- package/dist/mcp/tools/schema.js +317 -0
- package/dist/mcp/tools/system.d.ts +3 -0
- package/dist/mcp/tools/system.js +22 -0
- package/dist/mcp/tools/trigger-flow.d.ts +8 -0
- package/dist/mcp/tools/trigger-flow.js +48 -0
- package/dist/mcp/transport.d.ts +13 -0
- package/dist/mcp/transport.js +18 -0
- package/dist/mcp/types.d.ts +56 -0
- package/dist/mcp/types.js +1 -0
- package/dist/services/authentication.js +36 -0
- package/dist/services/fields.js +4 -4
- package/dist/services/items.js +14 -4
- package/dist/services/payload.d.ts +7 -3
- package/dist/services/payload.js +26 -12
- package/dist/services/server.js +1 -0
- package/dist/services/tfa.d.ts +1 -1
- package/dist/services/tfa.js +20 -5
- package/dist/services/versions.d.ts +6 -4
- package/dist/services/versions.js +84 -25
- package/dist/types/auth.d.ts +2 -1
- package/dist/utils/versioning/deep-map-with-schema.d.ts +23 -0
- package/dist/utils/versioning/deep-map-with-schema.js +81 -0
- package/dist/utils/versioning/handle-version.d.ts +2 -2
- package/dist/utils/versioning/handle-version.js +47 -43
- package/dist/utils/versioning/split-recursive.d.ts +4 -0
- package/dist/utils/versioning/split-recursive.js +27 -0
- package/package.json +30 -29
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
Perform CRUD operations on Directus Fields.
|
|
2
|
+
|
|
3
|
+
<actions>
|
|
4
|
+
- `create`: Add one or multiple fields to a collection
|
|
5
|
+
- `read`: View field configurations
|
|
6
|
+
- `update`: Update one or multiple fields
|
|
7
|
+
- `delete`: Remove fields
|
|
8
|
+
</actions>
|
|
9
|
+
|
|
10
|
+
<field_types>
|
|
11
|
+
|
|
12
|
+
- **Text**: `string` (max 255 chars), `text` (unlimited), `uuid` (relations/IDs), `hash` (passwords)
|
|
13
|
+
- **Numeric**: `integer`, `bigInteger`, `float`, `decimal` (for financial precision)
|
|
14
|
+
- **Date/Time**: `timestamp`, `datetime`, `date`, `time`
|
|
15
|
+
- **Boolean**: `boolean` for toggles/flags
|
|
16
|
+
- **Structured**: `json` (complex data), `csv` (tags/lists)
|
|
17
|
+
- **Alias**: Virtual fields for relations (`o2m`, `m2m`, `m2a`, `files`, `translations`)
|
|
18
|
+
- **Geospatial**: `point`, `lineString`, `polygon` for maps </field_types>
|
|
19
|
+
|
|
20
|
+
<adding_fields>
|
|
21
|
+
|
|
22
|
+
**Important**: When using the `fields` tool, `data` must always be an array of field objects, even for single fields.
|
|
23
|
+
Make sure you include `meta` and `schema` objects for each field.
|
|
24
|
+
|
|
25
|
+
Add fields to existing collections:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"action": "create",
|
|
30
|
+
"collection": "articles",
|
|
31
|
+
"data": [
|
|
32
|
+
{
|
|
33
|
+
"field": "excerpt",
|
|
34
|
+
"type": "text",
|
|
35
|
+
"meta": {
|
|
36
|
+
"interface": "input-rich-text-md",
|
|
37
|
+
"special": null,
|
|
38
|
+
"note": "Article excerpt for previews and SEO. Supports markdown formatting.",
|
|
39
|
+
"translations": [
|
|
40
|
+
{
|
|
41
|
+
"language": "en-US",
|
|
42
|
+
"translation": "Excerpt"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"options": {
|
|
46
|
+
"placeholder": null,
|
|
47
|
+
"customSyntax": null
|
|
48
|
+
},
|
|
49
|
+
"display": "formatted-value",
|
|
50
|
+
"display_options": { "format": true }
|
|
51
|
+
},
|
|
52
|
+
"schema": {
|
|
53
|
+
"name": "test",
|
|
54
|
+
"table": "random_collection",
|
|
55
|
+
"data_type": "text"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Multiple Fields Example:**
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"action": "create",
|
|
67
|
+
"collection": "articles",
|
|
68
|
+
"data": [
|
|
69
|
+
{
|
|
70
|
+
"field": "title",
|
|
71
|
+
"type": "string"
|
|
72
|
+
// Rest of field data
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"field": "content",
|
|
76
|
+
"type": "text"
|
|
77
|
+
// Rest of field data
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Note**: You can omit `null` or `false` values from the schema object. </adding_fields>
|
|
84
|
+
|
|
85
|
+
<relationship_fields>
|
|
86
|
+
|
|
87
|
+
**CRITICAL**: Field type and meta.special determine relationship behavior.
|
|
88
|
+
|
|
89
|
+
- **M2O**: `type: "uuid"`, `special: ["m2o"]`, interface: `select-dropdown-m2o` → then create relation
|
|
90
|
+
- **O2M**: `type: "alias"`, `special: ["o2m"]`, interface: `list-o2m` → auto-created with M2O
|
|
91
|
+
- **M2M**: `type: "alias"`, `special: ["m2m"]`, interface: `list-m2m` → needs junction collection
|
|
92
|
+
- **M2A**: `type: "alias"`, `special: ["m2a"]`, interface: `list-m2a` → polymorphic, needs junction
|
|
93
|
+
- **File**: `type: "uuid"`, `special: ["file"]`, interface: `file` or `file-image` → single file relation
|
|
94
|
+
- **Files**: `type: "alias"`, `special: ["files"]`, interface: `files` → multiple files via M2M
|
|
95
|
+
- **Translations**: `type: "alias"`, `special: ["translations"]`, interface: `translations` → special M2M
|
|
96
|
+
|
|
97
|
+
### M2O Field Example
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"collection": "posts",
|
|
102
|
+
"field": "author",
|
|
103
|
+
"type": "uuid",
|
|
104
|
+
"schema": {
|
|
105
|
+
"name": "author",
|
|
106
|
+
"table": "posts",
|
|
107
|
+
"data_type": "uuid",
|
|
108
|
+
"is_nullable": true,
|
|
109
|
+
"foreign_key_schema": "public",
|
|
110
|
+
"foreign_key_table": "team",
|
|
111
|
+
"foreign_key_column": "id"
|
|
112
|
+
},
|
|
113
|
+
"meta": {
|
|
114
|
+
"collection": "posts",
|
|
115
|
+
"field": "author",
|
|
116
|
+
"special": ["m2o"],
|
|
117
|
+
"interface": "select-dropdown-m2o",
|
|
118
|
+
"options": {
|
|
119
|
+
"template": "{{image.$thumbnail}} {{name}}"
|
|
120
|
+
},
|
|
121
|
+
"display": "related-values",
|
|
122
|
+
"display_options": {
|
|
123
|
+
"template": "{{image.$thumbnail}} {{name}}"
|
|
124
|
+
},
|
|
125
|
+
"sort": 15,
|
|
126
|
+
"width": "half"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### O2M Field Example
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"collection": "posts",
|
|
136
|
+
"field": "comments",
|
|
137
|
+
"type": "alias",
|
|
138
|
+
"schema": null,
|
|
139
|
+
"meta": {
|
|
140
|
+
"collection": "posts",
|
|
141
|
+
"field": "comments",
|
|
142
|
+
"special": ["o2m"],
|
|
143
|
+
"interface": "list-o2m",
|
|
144
|
+
"options": {
|
|
145
|
+
"template": "{{author}} - {{content}} ({{status}})"
|
|
146
|
+
},
|
|
147
|
+
"display": "related-values",
|
|
148
|
+
"display_options": {
|
|
149
|
+
"template": "{{author}} - {{content}} ({{status}})"
|
|
150
|
+
},
|
|
151
|
+
"sort": 10,
|
|
152
|
+
"width": "full",
|
|
153
|
+
"required": false,
|
|
154
|
+
"group": null
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### M2M Field Example
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"collection": "posts",
|
|
164
|
+
"field": "categories",
|
|
165
|
+
"type": "alias",
|
|
166
|
+
"schema": null,
|
|
167
|
+
"meta": {
|
|
168
|
+
"collection": "posts",
|
|
169
|
+
"field": "categories",
|
|
170
|
+
"special": ["m2m"],
|
|
171
|
+
"interface": "list-m2m",
|
|
172
|
+
"options": {
|
|
173
|
+
"template": "{{categories_id.name}} ({{categories_id.slug}})"
|
|
174
|
+
},
|
|
175
|
+
"display": "related-values",
|
|
176
|
+
"display_options": {
|
|
177
|
+
"template": "{{categories_id.name}} ({{categories_id.slug}})"
|
|
178
|
+
},
|
|
179
|
+
"sort": 9,
|
|
180
|
+
"width": "full"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### M2A Field Example
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"collection": "pages",
|
|
190
|
+
"field": "blocks",
|
|
191
|
+
"type": "alias",
|
|
192
|
+
"schema": null,
|
|
193
|
+
"meta": {
|
|
194
|
+
"collection": "pages",
|
|
195
|
+
"field": "blocks",
|
|
196
|
+
"special": ["m2a"],
|
|
197
|
+
"interface": "list-m2a",
|
|
198
|
+
"options": {},
|
|
199
|
+
"display": "related-values",
|
|
200
|
+
"display_options": {
|
|
201
|
+
"template": "{{collection}}"
|
|
202
|
+
},
|
|
203
|
+
"sort": 8,
|
|
204
|
+
"width": "full"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### File Field Example
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"collection": "posts",
|
|
214
|
+
"field": "featured_image",
|
|
215
|
+
"type": "uuid",
|
|
216
|
+
"schema": {
|
|
217
|
+
"name": "featured_image",
|
|
218
|
+
"table": "posts",
|
|
219
|
+
"data_type": "uuid",
|
|
220
|
+
"is_nullable": true,
|
|
221
|
+
"foreign_key_schema": "public",
|
|
222
|
+
"foreign_key_table": "directus_files",
|
|
223
|
+
"foreign_key_column": "id"
|
|
224
|
+
},
|
|
225
|
+
"meta": {
|
|
226
|
+
"collection": "posts",
|
|
227
|
+
"field": "featured_image",
|
|
228
|
+
"special": ["file"],
|
|
229
|
+
"interface": "file-image",
|
|
230
|
+
"options": {
|
|
231
|
+
"folder": "post-images"
|
|
232
|
+
},
|
|
233
|
+
"display": "image",
|
|
234
|
+
"display_options": null,
|
|
235
|
+
"sort": 1,
|
|
236
|
+
"width": "half",
|
|
237
|
+
"required": false,
|
|
238
|
+
"group": "media"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Files Field Example
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"collection": "posts",
|
|
248
|
+
"field": "gallery",
|
|
249
|
+
"type": "alias",
|
|
250
|
+
"schema": null,
|
|
251
|
+
"meta": {
|
|
252
|
+
"collection": "posts",
|
|
253
|
+
"field": "gallery",
|
|
254
|
+
"special": ["files"],
|
|
255
|
+
"interface": "files",
|
|
256
|
+
"options": null,
|
|
257
|
+
"display": "related-values",
|
|
258
|
+
"display_options": null,
|
|
259
|
+
"sort": 4,
|
|
260
|
+
"width": "full"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Translations Field Example
|
|
266
|
+
|
|
267
|
+
```json
|
|
268
|
+
{
|
|
269
|
+
"collection": "posts",
|
|
270
|
+
"field": "translations",
|
|
271
|
+
"type": "alias",
|
|
272
|
+
"schema": null,
|
|
273
|
+
"meta": {
|
|
274
|
+
"collection": "posts",
|
|
275
|
+
"field": "translations",
|
|
276
|
+
"special": ["translations"],
|
|
277
|
+
"interface": "translations",
|
|
278
|
+
"options": {
|
|
279
|
+
"userLanguage": true,
|
|
280
|
+
"defaultOpenSplitView": true
|
|
281
|
+
},
|
|
282
|
+
"display": "translations",
|
|
283
|
+
"display_options": {
|
|
284
|
+
"template": "{{title}}", // Field to display from the translated collection (ie post title)
|
|
285
|
+
"languageField": "name" // Name of the language field from the languages collection
|
|
286
|
+
},
|
|
287
|
+
"sort": 22,
|
|
288
|
+
"width": "full"
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Note**: Alias fields don't need a schema object since they're virtual. </relationship_fields>
|
|
294
|
+
|
|
295
|
+
<primary_keys> **🎯 ALWAYS use UUID as primary keys for new collections unless integers or manually entered strings ares
|
|
296
|
+
specifically requested by the user.**
|
|
297
|
+
|
|
298
|
+
**UUID Primary Key Template:**
|
|
299
|
+
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"field": "id",
|
|
303
|
+
"type": "uuid",
|
|
304
|
+
"meta": { "hidden": true, "readonly": true, "interface": "input", "special": ["uuid"] },
|
|
305
|
+
"schema": { "is_primary_key": true, "length": 36, "has_auto_increment": false }
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
</primary_keys>
|
|
310
|
+
|
|
311
|
+
<interfaces>
|
|
312
|
+
## Common Interfaces
|
|
313
|
+
|
|
314
|
+
**Text**: `input`, `input-multiline`, `input-rich-text-md`, `input-rich-text-html`, `input-hash`, `translations`
|
|
315
|
+
**Selection**: `select-dropdown`, `select-multiple-dropdown`, `select-radio`, `select-multiple-checkbox`, `tags`,
|
|
316
|
+
`boolean`, `slider` **Date/Time**: `datetime`, `date`, `time` **Relational**: `select-dropdown-m2o`, `list-o2m`,
|
|
317
|
+
`list-m2m`, `list-m2a` **Files**: `file`, `files`, `file-image` **Advanced**: `input-code`, `map`, `group-raw`,
|
|
318
|
+
`group-detail` </interfaces>
|
|
319
|
+
|
|
320
|
+
<field_configuration>
|
|
321
|
+
|
|
322
|
+
### Layout
|
|
323
|
+
|
|
324
|
+
- **width**: `"half"` (380px max), `"full"` (760px max, default), `"fill"` (no limit)
|
|
325
|
+
- **sort**: Field order in forms
|
|
326
|
+
- **group**: Group related fields into collapsible sections (must be used with `alias` group fields)
|
|
327
|
+
|
|
328
|
+
### Schema Properties
|
|
329
|
+
|
|
330
|
+
- **default_value**: Default for new items
|
|
331
|
+
- **is_nullable**: Can be null
|
|
332
|
+
- **is_unique**: Must be unique
|
|
333
|
+
- **length**: Max length for strings
|
|
334
|
+
|
|
335
|
+
### Meta Properties
|
|
336
|
+
|
|
337
|
+
- **required**: Must have value
|
|
338
|
+
- **readonly**: Cannot edit after creation
|
|
339
|
+
- **hidden**: Hidden from UI (still in API)
|
|
340
|
+
- **validation**: Custom validation rules
|
|
341
|
+
- **validation_message**: Custom error messages
|
|
342
|
+
- **note**: Context for non-obvious fields
|
|
343
|
+
|
|
344
|
+
### Conditions
|
|
345
|
+
|
|
346
|
+
Dynamically control field behavior based on other field values:
|
|
347
|
+
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"conditions": [
|
|
351
|
+
{
|
|
352
|
+
"name": "Hide If Author Is Null",
|
|
353
|
+
"rule": {
|
|
354
|
+
"_and": [
|
|
355
|
+
{
|
|
356
|
+
"author": {
|
|
357
|
+
"_null": true
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
]
|
|
361
|
+
},
|
|
362
|
+
"hidden": true
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"name": "Required If Published",
|
|
366
|
+
"rule": {
|
|
367
|
+
"status": {
|
|
368
|
+
"_eq": "published"
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
"required": true
|
|
372
|
+
}
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Condition Properties**:
|
|
378
|
+
|
|
379
|
+
- `name`: Description of the condition
|
|
380
|
+
- `rule`: Filter rules using Directus filter syntax
|
|
381
|
+
- Can set: `hidden`, `readonly`, `required`, or interface-specific options
|
|
382
|
+
|
|
383
|
+
**Common Rules**:
|
|
384
|
+
|
|
385
|
+
- `_null`: Check if field is null
|
|
386
|
+
- `_eq`: Equals specific value
|
|
387
|
+
- `_neq`: Not equals
|
|
388
|
+
- `_in`: Value in array
|
|
389
|
+
- `_and`/`_or`: Combine multiple conditions
|
|
390
|
+
|
|
391
|
+
### Special Fields
|
|
392
|
+
|
|
393
|
+
- `special: ["uuid"]`: Auto-generate UUID
|
|
394
|
+
- `special: ["user-created"]`: Track creating user
|
|
395
|
+
- `special: ["date-created"]`: Track creation time
|
|
396
|
+
- `special: ["user-updated"]`: Track last editor
|
|
397
|
+
- `special: ["date-updated"]`: Track last edit time
|
|
398
|
+
- `special: ["cast-json"]`: Cast JSON strings to objects </field_configuration>
|
|
399
|
+
|
|
400
|
+
<translations>
|
|
401
|
+
Field names can (and should be) translated for editors using the app.
|
|
402
|
+
Check for `languages` collection first, then add field translations based on which languages are stored in DB. IF not 99% sure, confirm with user first.
|
|
403
|
+
|
|
404
|
+
```json
|
|
405
|
+
"translations": [
|
|
406
|
+
{"language": "en-US", "translation": "Title"},
|
|
407
|
+
{"language": "es-ES", "translation": "Título"}
|
|
408
|
+
]
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
</translations>
|
|
412
|
+
|
|
413
|
+
<display_templates> Display templates can be customized used to enhance the UX for editors.
|
|
414
|
+
|
|
415
|
+
```json
|
|
416
|
+
"display": "related-values",
|
|
417
|
+
"display_options": {
|
|
418
|
+
"template": "{{first_name}} {{last_name}}"
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
**Display types**: `raw`, `formatted-value`, `labels`, `datetime`, `user`, `file`, `related-values` </display_templates>
|
|
423
|
+
|
|
424
|
+
<complete_example>
|
|
425
|
+
|
|
426
|
+
#### Complete Field Example with Advanced Features
|
|
427
|
+
|
|
428
|
+
This shows a real field configuration with validation, conditions, and all metadata (as returned from a read operation):
|
|
429
|
+
|
|
430
|
+
```json
|
|
431
|
+
{
|
|
432
|
+
"collection": "block_button",
|
|
433
|
+
"field": "url",
|
|
434
|
+
"type": "string",
|
|
435
|
+
"schema": {
|
|
436
|
+
"name": "url",
|
|
437
|
+
"table": "block_button",
|
|
438
|
+
"data_type": "character varying", // Database-specific type
|
|
439
|
+
"default_value": null,
|
|
440
|
+
"generation_expression": null,
|
|
441
|
+
"max_length": 255, // String length limit
|
|
442
|
+
"numeric_precision": null,
|
|
443
|
+
"numeric_scale": null,
|
|
444
|
+
"is_generated": false,
|
|
445
|
+
"is_nullable": true,
|
|
446
|
+
"is_unique": false,
|
|
447
|
+
"is_indexed": false,
|
|
448
|
+
"is_primary_key": false,
|
|
449
|
+
"has_auto_increment": false,
|
|
450
|
+
"foreign_key_schema": null, // Would contain relation info for M2O fields
|
|
451
|
+
"foreign_key_table": null,
|
|
452
|
+
"foreign_key_column": null,
|
|
453
|
+
"comment": null
|
|
454
|
+
},
|
|
455
|
+
"meta": {
|
|
456
|
+
"id": 811, // Auto-generated field ID (not used in create)
|
|
457
|
+
"collection": "block_button",
|
|
458
|
+
"field": "url",
|
|
459
|
+
"special": null, // No special behavior for this field
|
|
460
|
+
"interface": "input",
|
|
461
|
+
"options": {
|
|
462
|
+
"iconLeft": "link", // Icon displayed in the input
|
|
463
|
+
"trim": true // Remove whitespace on save
|
|
464
|
+
},
|
|
465
|
+
"display": "formatted-value",
|
|
466
|
+
"display_options": {
|
|
467
|
+
"format": true // Apply auto formatting based on field type
|
|
468
|
+
},
|
|
469
|
+
"readonly": false,
|
|
470
|
+
"hidden": true, // Hidden by default, shown conditionally
|
|
471
|
+
"sort": 11, // Field order in forms
|
|
472
|
+
"width": "half",
|
|
473
|
+
"translations": null, // No field name translations
|
|
474
|
+
"note": "The URL to link to. Could be relative (ie `/my-page`) or a full external URL (ie `https://docs.directus.io`)",
|
|
475
|
+
"conditions": [
|
|
476
|
+
{
|
|
477
|
+
"hidden": false, // Show field when condition is met
|
|
478
|
+
"name": "If type = external",
|
|
479
|
+
"options": {
|
|
480
|
+
"clear": false,
|
|
481
|
+
"font": "sans-serif",
|
|
482
|
+
"masked": false,
|
|
483
|
+
"slug": false,
|
|
484
|
+
"trim": false
|
|
485
|
+
},
|
|
486
|
+
"rule": {
|
|
487
|
+
"_and": [
|
|
488
|
+
{
|
|
489
|
+
"type": {
|
|
490
|
+
// Show when 'type' field equals 'url'
|
|
491
|
+
"_eq": "url"
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
]
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
],
|
|
498
|
+
"required": false,
|
|
499
|
+
"group": null,
|
|
500
|
+
"validation": {
|
|
501
|
+
"_and": [
|
|
502
|
+
{
|
|
503
|
+
"url": {
|
|
504
|
+
"_regex": "^(?:\\/[A-Za-z0-9\\-._~%!$&'()*+,;=:@\\/]*|https?:\\/\\/[^\\s/$.?#].[^\\s]*)$"
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
]
|
|
508
|
+
}, // Regex validation for URLs (relative or absolute)
|
|
509
|
+
"validation_message": "Invalid URL. Check your URL and try again. Properly formatted relative URLs (`/pages/test` ) and absolute URLs (`https://example.com`) are supported."
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
</complete_example>
|
|
515
|
+
|
|
516
|
+
<related_tools>
|
|
517
|
+
|
|
518
|
+
## Related Tools
|
|
519
|
+
|
|
520
|
+
- `collections`: Create containers for fields
|
|
521
|
+
- `relations`: Connect fields between collections </related_tools>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
Perform CRUD operations on files in Directus.
|
|
2
|
+
|
|
3
|
+
## Actions
|
|
4
|
+
|
|
5
|
+
- **`read`**: List/query metadata or get specific items by ID
|
|
6
|
+
- **`update`**: Modify existing metadata
|
|
7
|
+
- **`delete`**: Remove files by keys
|
|
8
|
+
- **`import`**: Import a file from a URL and create or update its file data
|
|
9
|
+
|
|
10
|
+
## Example Operations
|
|
11
|
+
|
|
12
|
+
### Reading File Metadata
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"action": "read",
|
|
17
|
+
"query": {
|
|
18
|
+
"fields": ["id", "title", "type", "filesize", "width", "height"],
|
|
19
|
+
"filter": { "type": { "_starts_with": "image/" } },
|
|
20
|
+
"limit": 10
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Get Single File Metadata
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"action": "read",
|
|
30
|
+
"keys": ["file-uuid-here"]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Import a File via URL
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"action": "import",
|
|
39
|
+
"data": [
|
|
40
|
+
{
|
|
41
|
+
"url": "file-url",
|
|
42
|
+
"file": {
|
|
43
|
+
"title": "New Title",
|
|
44
|
+
"description": "Updated description",
|
|
45
|
+
"tags": ["tag1", "tag2", "category"],
|
|
46
|
+
"folder": "folder-uuid"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Update File Metadata
|
|
54
|
+
|
|
55
|
+
**Single file:**
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"action": "update",
|
|
60
|
+
"keys": ["file-uuid"],
|
|
61
|
+
"data": {
|
|
62
|
+
"title": "New Title",
|
|
63
|
+
"description": "Updated description",
|
|
64
|
+
"tags": ["tag1", "tag2", "category"],
|
|
65
|
+
"folder": "folder-uuid"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Batch update:**
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"action": "update",
|
|
75
|
+
"data": [
|
|
76
|
+
{ "id": "file-uuid-1", "title": "New Title 1" },
|
|
77
|
+
{ "id": "file-uuid-2", "title": "New Title 2" }
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Common Filters
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"query": {
|
|
87
|
+
"filter": {
|
|
88
|
+
"_and": [
|
|
89
|
+
{ "type": { "_icontains": "/png" } }, // PNG files only
|
|
90
|
+
{ "folder": { "_eq": "folder-uuid" } }, // Specific folder
|
|
91
|
+
{ "filesize": { "_lt": 5000000 } }, // Under 5MB
|
|
92
|
+
{ "uploaded_on": { "_gte": "$NOW(-7 days)" } } // Within last week
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## File Metadata Fields
|
|
100
|
+
|
|
101
|
+
- `id`: Unique identifier
|
|
102
|
+
- `storage`: Storage adapter used
|
|
103
|
+
- `filename_disk`: Actual filename on disk
|
|
104
|
+
- `filename_download`: Suggested download filename
|
|
105
|
+
- `title`: Display title
|
|
106
|
+
- `type`: MIME type (e.g., "image/jpeg", "application/pdf")
|
|
107
|
+
- `folder`: Parent folder ID
|
|
108
|
+
- `uploaded_by`: User who uploaded
|
|
109
|
+
- `uploaded_on`: Upload timestamp
|
|
110
|
+
- `modified_by`: Last modifier
|
|
111
|
+
- `modified_on`: Last modification time
|
|
112
|
+
- `filesize`: Size in bytes
|
|
113
|
+
- `width`/`height`: Dimensions for images (in pixels)
|
|
114
|
+
- `duration`: Length for video/audio
|
|
115
|
+
- `description`: File description
|
|
116
|
+
- `location`: Geo-location data
|
|
117
|
+
- `tags`: Array of tag strings (e.g., ["product", "red", "handbag"])
|
|
118
|
+
- `metadata`: Additional metadata object
|
|
119
|
+
- `focal_point_x`: Horizontal focal point (in pixels from left edge)
|
|
120
|
+
- `focal_point_y`: Vertical focal point (in pixels from top edge)
|
|
121
|
+
|
|
122
|
+
## Real-World Use Cases
|
|
123
|
+
|
|
124
|
+
### Asset Selection for Content
|
|
125
|
+
|
|
126
|
+
Find appropriate images for articles, pages, or products:
|
|
127
|
+
|
|
128
|
+
_Example: "Find images in our asset library related to customer support for our new help center article."_
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"action": "read",
|
|
133
|
+
"query": {
|
|
134
|
+
"fields": ["id", "title", "description", "tags", "type"],
|
|
135
|
+
"search": "help center"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Asset Organization & Cleanup
|
|
141
|
+
|
|
142
|
+
Transform generic files into well-organized, searchable assets:
|
|
143
|
+
|
|
144
|
+
1. **Find files needing metadata:**
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"action": "read",
|
|
149
|
+
"query": {
|
|
150
|
+
"fields": ["id", "filename_disk", "title", "description"],
|
|
151
|
+
"filter": { "description": { "_null": true } }
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
2. **Analyze with vision (use `assets` tool for base64):** Get image content for AI analysis
|
|
157
|
+
|
|
158
|
+
3. **Update with descriptive metadata:**
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"action": "update",
|
|
163
|
+
"keys": ["image-uuid"],
|
|
164
|
+
"data": {
|
|
165
|
+
"title": "Red leather handbag product photo",
|
|
166
|
+
"description": "Professional e-commerce photo with white background",
|
|
167
|
+
"tags": ["handbag", "leather", "red", "product-photo", "accessories"],
|
|
168
|
+
"focal_point_x": 512,
|
|
169
|
+
"focal_point_y": 300 // Focal points ensure that when images are cropped for different aspect ratios (thumbnails, hero images, etc.), the important subject remains visible. Coordinates are in pixels from the top-left corner of the original image.
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Key Points
|
|
175
|
+
|
|
176
|
+
- **ALWAYS pass data as native objects**, NOT stringified JSON
|
|
177
|
+
- **Metadata only**: This tool manages file metadata, not file content or uploads
|
|
178
|
+
- **Permissions**: Respects Directus access control
|
|
179
|
+
- **Arrays required**: `keys` and `tags` must be arrays: `["item"]` not `"item"`
|
|
180
|
+
- **Performance**: Large files handled automatically but may impact performance
|