@directus/api 32.0.1 → 32.1.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.
@@ -146,309 +146,72 @@ can read existing operations to see if they are using extensions operations. </a
146
146
 
147
147
  <workflow_creation>
148
148
 
149
- ## Workflow Creation Process - **ESSENTIAL READING**
149
+ ## Workflow Creation Process
150
150
 
151
- **⚠️ CRITICAL**: Follow this exact order or operations will fail
151
+ **Critical Order:** Create flow first Create operations with null resolve/reject → Link operations via UUIDs → Update
152
+ flow entry point.
152
153
 
153
- <workflow_steps>
154
-
155
- ### Step-by-Step Process:
156
-
157
- 1. **Create the flow** using the `flows` tool
158
- 2. **Create all operations** with null resolve/reject initially
159
- 3. **Link operations together** using the UUIDs returned from step 2
160
- 4. **Update the flow** to set the first operation as the entry point
161
-
162
- ### Why This Order Matters:
163
-
164
- - Operations must exist before they can be referenced in resolve/reject fields
165
- - UUIDs are only available after operations are created
166
- - The flow needs at least one operation created before setting its entry point </workflow_steps>
167
-
168
- <workflow_example>
169
-
170
- ### Complete Workflow Example:
171
-
172
- ```json
173
- // Step 1: Create the flow first (using flows tool)
174
- {
175
- "action": "create",
176
- "data": {
177
- "name": "Email on Post Published",
178
- "trigger": "event",
179
- "options": {
180
- "type": "action",
181
- "scope": ["items.create"],
182
- "collections": ["posts"]
183
- }
184
- }
185
- }
186
- // Returns: {"id": "flow-uuid-123", ...}
187
-
188
- // Step 2: Create operations with null connections initially
189
- {"action": "create", "data": {
190
- "flow": "flow-uuid-123",
191
- "key": "check_status",
192
- "type": "condition",
193
- "position_x": 19, // First operation position
194
- "position_y": 1,
195
- "options": {
196
- "filter": {
197
- "$trigger": {
198
- "payload": {
199
- "status": {"_eq": "published"}
200
- }
201
- }
202
- }
203
- },
204
- "resolve": null, // Set to null initially
205
- "reject": null // Set to null initially
206
- }}
207
- // Returns: {"id": "condition-uuid-456", ...}
208
-
209
- {"action": "create", "data": {
210
- "flow": "flow-uuid-123",
211
- "key": "send_email",
212
- "type": "mail",
213
- "position_x": 37, // Second operation position
214
- "position_y": 1,
215
- "options": {
216
- "to": ["admin@example.com"],
217
- "subject": "New post published",
218
- "body": "Post '{{$trigger.payload.title}}' was published"
219
- },
220
- "resolve": null,
221
- "reject": null
222
- }}
223
- // Returns: {"id": "email-uuid-789", ...}
224
-
225
- // Step 3: Connect operations using UUIDs (NOT keys)
226
- {"action": "update", "key": "condition-uuid-456", "data": {
227
- "resolve": "email-uuid-789", // Use UUID from step 2
228
- "reject": null // No error handling operation
229
- }}
230
-
231
- // Step 4: Update flow to set first operation (using flows tool)
232
- {"action": "update", "key": "flow-uuid-123", "data": {
233
- "operation": "condition-uuid-456" // First operation UUID
234
- }}
235
- ```
236
-
237
- </workflow_example> </workflow_creation>
154
+ **See `flows` tool for complete workflow example with detailed steps.** </workflow_creation>
238
155
 
239
156
  <positioning_system>
240
157
 
241
- ## Grid-Based Positioning - **ALWAYS SET POSITIONS**
242
-
243
- **Grid Rules:**
244
-
245
- - Each operation: 14x14 grid units
246
- - Standard spacing: 18 units (19, 37, 55, 73...)
247
- - Vertical start: `position_y: 1`
248
- - Never use (0,0) - operations will overlap
249
-
250
- **Common Patterns:**
251
-
252
- ```json
253
- // Linear flow
254
- {"position_x": 19, "position_y": 1} // First
255
- {"position_x": 37, "position_y": 1} // Second
256
- {"position_x": 55, "position_y": 1} // Third
257
-
258
- // Branching (success/error)
259
- {"position_x": 19, "position_y": 1} // Main
260
- {"position_x": 37, "position_y": 1} // Success (same row)
261
- {"position_x": 37, "position_y": 19} // Error (lower row)
262
- ```
263
-
264
- </positioning_system>
265
-
266
- <operation_examples> <condition> Evaluates filter rules to determine path
267
-
268
- ```json
269
- {
270
- "type": "condition",
271
- "options": {
272
- "filter": {
273
- "$trigger": {
274
- "payload": {
275
- "status": { "_eq": "published" }
276
- }
277
- }
278
- }
279
- }
280
- }
281
- ```
282
-
283
- <filter_examples>
284
-
285
- ```json
286
- // Check if field exists
287
- {
288
- "filter": {
289
- "$trigger": {
290
- "payload": {
291
- "website": {"_nnull": true}
292
- }
293
- }
294
- }
295
- }
296
-
297
- // Multiple conditions (AND) - CORRECTED SYNTAX
298
- {
299
- "filter": {
300
- "$trigger": {
301
- "payload": {
302
- "_and": [
303
- {"status": {"_eq": "published"}},
304
- {"featured": {"_eq": true}}
305
- ]
306
- }
307
- }
308
- }
309
- }
310
- ```
311
-
312
- </filter_examples> </condition>
313
-
314
- <item_operations> **Create Items:**
158
+ ## Grid Positioning
315
159
 
316
- ```json
317
- {
318
- "type": "item-create",
319
- "options": {
320
- "collection": "notifications",
321
- "permissions": "$trigger",
322
- "emitEvents": true,
323
- "payload": {
324
- "title": "{{ $trigger.payload.title }}",
325
- "user": "{{ $accountability.user }}"
326
- }
327
- }
328
- }
329
- ```
160
+ **Rules:** 14x14 units, spacing every 18 units (example 19/37/55/73). Never (0,0). Start `position_y: 1`.
330
161
 
331
- **Read Items:**
162
+ **Patterns:** Linear (19,1)→(37,1)→(55,1). Branching: success (37,1), error (37,19). </positioning_system>
332
163
 
333
- ```json
334
- {
335
- "type": "item-read",
336
- "options": {
337
- "collection": "products",
338
- "permissions": "$full",
339
- "query": {
340
- "filter": { "status": { "_eq": "active" } },
341
- "limit": 10
342
- }
343
- }
344
- }
345
- ```
346
-
347
- **Update Items:**
164
+ <operation_examples> **condition** - Evaluates filter rules
348
165
 
349
166
  ```json
350
- {
351
- "type": "item-update",
352
- "options": {
353
- "collection": "orders",
354
- "permissions": "$trigger",
355
- "emitEvents": true,
356
- "key": "{{ $trigger.payload.id }}",
357
- "payload": { "status": "processed" }
358
- }
359
- }
167
+ { "type": "condition", "options": { "filter": { "$trigger": { "payload": { "status": { "_eq": "published" } } } } } }
168
+ // Multiple: {"_and": [{"status": {"_eq": "published"}}, {"featured": {"_eq": true}}]}
360
169
  ```
361
170
 
362
- **Delete Items:**
171
+ **item-create/read/update/delete** - CRUD operations
363
172
 
364
173
  ```json
365
- {
366
- "type": "item-delete",
367
- "options": {
368
- "collection": "temp_data",
369
- "permissions": "$full",
370
- "key": ["{{ read_items[0].id }}"]
371
- }
372
- }
174
+ {"type": "item-create", "options": {"collection": "notifications", "permissions": "$trigger", "payload": {"title": "{{ $trigger.payload.title }}"}}}
175
+ {"type": "item-read", "options": {"collection": "products", "query": {"filter": {"status": {"_eq": "active"}}}}}
176
+ {"type": "item-update", "options": {"collection": "orders", "key": "{{ $trigger.payload.id }}", "payload": {"status": "processed"}}}
177
+ {"type": "item-delete", "options": {"collection": "temp_data", "key": ["{{ read_items[0].id }}"]}}
373
178
  ```
374
179
 
375
- </item_operations>
376
-
377
- <exec>
378
- Execute custom JavaScript/TypeScript in isolated sandbox
379
-
380
- **⚠️ SECURITY WARNING**: Scripts run sandboxed with NO file system or network access
180
+ **exec** - Custom JavaScript/TypeScript (sandboxed, no file/network access)
381
181
 
382
182
  ```json
383
183
  {
384
184
  "type": "exec",
385
185
  "options": {
386
- "code": "module.exports = async function(data) {\n // Validate input\n if (!data.$trigger.payload.value) {\n throw new Error('Missing required value');\n }\n \n // Process data\n const result = data.$trigger.payload.value * 2;\n \n // Return must be valid JSON\n return {\n result: result,\n processed: true\n };\n}"
186
+ "code": "module.exports = async function(data) {\n const result = data.$trigger.payload.value * 2;\n return { result, processed: true };\n}"
387
187
  }
388
188
  }
389
189
  ```
390
190
 
391
- **Common Use Cases**: Data transformation, calculations, complex logic, formatting, extracting nested values </exec>
392
-
393
- <mail>
394
- Send email notifications with optional templates
191
+ **mail** - Send email (markdown/wysiwyg/template)
395
192
 
396
193
  ```json
397
194
  {
398
195
  "type": "mail",
399
196
  "options": {
400
- "to": ["user@example.com", "{{ $trigger.payload.email }}"],
197
+ "to": ["user@example.com"],
401
198
  "subject": "Order Confirmation",
402
- "type": "markdown", // "markdown" (default), "wysiwyg", or "template"
403
- "body": "Your order {{ $trigger.payload.order_id }} has been confirmed.",
404
- "cc": ["cc@example.com"], // Optional
405
- "bcc": ["bcc@example.com"], // Optional
406
- "replyTo": ["reply@example.com"] // Optional
199
+ "body": "Order {{ $trigger.payload.order_id }}"
407
200
  }
408
201
  }
202
+ // Template: {"type": "template", "template": "welcome-email", "data": {"username": "{{ $trigger.payload.name }}"}}
409
203
  ```
410
204
 
411
- **Template Mode:**
412
-
413
- ```json
414
- {
415
- "type": "mail",
416
- "options": {
417
- "to": ["{{ $trigger.payload.email }}"],
418
- "subject": "Welcome!",
419
- "type": "template",
420
- "template": "welcome-email", // Template name (default: "base")
421
- "data": {
422
- "username": "{{ $trigger.payload.name }}",
423
- "activation_url": "https://example.com/activate/{{ $trigger.payload.token }}"
424
- }
425
- }
426
- }
427
- ```
428
-
429
- </mail>
430
-
431
- <notification>
432
- Send in-app notifications to users
205
+ **notification** - In-app notifications
433
206
 
434
207
  ```json
435
208
  {
436
209
  "type": "notification",
437
- "options": {
438
- "recipient": ["{{ $accountability.user }}"], // User ID(s) to notify
439
- "subject": "Task Complete",
440
- "message": "Your export is ready for download",
441
- "permissions": "$trigger",
442
- "collection": "exports", // Optional: Related collection
443
- "item": "{{ create_export.id }}" // Optional: Related item ID
444
- }
210
+ "options": { "recipient": ["{{ $accountability.user }}"], "subject": "Task Complete", "message": "Export ready" }
445
211
  }
446
212
  ```
447
213
 
448
- </notification>
449
-
450
- <request>
451
- Make HTTP requests
214
+ **request** - HTTP requests (headers must be array of objects, body as stringified JSON)
452
215
 
453
216
  ```json
454
217
  {
@@ -456,146 +219,57 @@ Make HTTP requests
456
219
  "options": {
457
220
  "method": "POST",
458
221
  "url": "https://api.example.com/webhook",
459
- "headers": [
460
- {
461
- "header": "Authorization",
462
- "value": "Bearer {{ $env.API_TOKEN }}"
463
- },
464
- {
465
- "header": "Content-Type",
466
- "value": "application/json"
467
- }
468
- ],
469
- "body": "{\"data\": \"{{ process_data }}\", \"timestamp\": \"{{ $trigger.timestamp }}\"}"
222
+ "headers": [{ "header": "Authorization", "value": "Bearer {{ $env.API_TOKEN }}" }],
223
+ "body": "{\"data\": \"{{ process_data }}\"}"
470
224
  }
471
225
  }
472
226
  ```
473
227
 
474
- **Real Example (Netlify Deploy Hook)**:
475
-
476
- ```json
477
- {
478
- "type": "request",
479
- "options": {
480
- "method": "POST",
481
- "url": "https://api.netlify.com/build_hooks/your-hook-id",
482
- "headers": [
483
- {
484
- "header": "User-Agent",
485
- "value": "Directus-Flow/1.0"
486
- }
487
- ],
488
- "body": "{\"trigger\": \"content_updated\", \"item_id\": \"{{ $trigger.payload.id }}\"}"
489
- }
490
- }
491
- ```
492
-
493
- </request>
494
-
495
- <json_web_token> Sign, verify, or decode JWT tokens - **CONSOLIDATED EXAMPLE**
228
+ **json-web-token** - Sign/verify/decode JWT
496
229
 
497
230
  ```json
498
231
  {
499
232
  "type": "json-web-token",
500
233
  "options": {
501
- "operation": "sign", // "sign", "verify", or "decode"
502
-
503
- // For SIGN operations:
504
- "payload": {
505
- "userId": "{{ $trigger.payload.user }}",
506
- "role": "{{ $trigger.payload.role }}"
507
- },
234
+ "operation": "sign",
235
+ "payload": { "userId": "{{ $trigger.payload.user }}" },
508
236
  "secret": "{{ $env.JWT_SECRET }}",
509
- "options": {
510
- "expiresIn": "1h",
511
- "algorithm": "HS256"
512
- },
513
-
514
- // For VERIFY/DECODE operations:
515
- "token": "{{ $trigger.payload.token }}"
516
- // "secret": "{{ $env.JWT_SECRET }}", // Required for verify, not for decode
517
- // "options": {"algorithms": ["HS256"]}, // For verify
518
- // "options": {"complete": true} // For decode
237
+ "options": { "expiresIn": "1h" }
519
238
  }
520
239
  }
240
+ // Verify: {"operation": "verify", "token": "{{ $trigger.payload.token }}", "secret": "{{ $env.JWT_SECRET }}"}
521
241
  ```
522
242
 
523
- </json_web_token>
524
-
525
- <other_operations> **Transform JSON:**
243
+ **transform** - Create custom JSON payloads
526
244
 
527
245
  ```json
528
246
  {
529
247
  "type": "transform",
530
- "options": {
531
- "json": {
532
- "combined": {
533
- "user": "{{ $accountability.user }}",
534
- "items": "{{ read_items }}",
535
- "timestamp": "{{ $trigger.timestamp }}"
536
- }
537
- }
538
- }
248
+ "options": { "json": { "combined": { "user": "{{ $accountability.user }}", "items": "{{ read_items }}" } } }
539
249
  }
540
250
  ```
541
251
 
542
- **Trigger Flow:**
252
+ **trigger** - Execute another flow
543
253
 
544
254
  ```json
545
255
  {
546
256
  "type": "trigger",
547
- "options": {
548
- "flow": "other-flow-uuid",
549
- "payload": { "data": "{{ transform_result }}" },
550
- "iterationMode": "parallel", // "parallel", "serial", "batch"
551
- "batchSize": 10 // Only for batch mode
552
- }
553
- }
554
- ```
555
-
556
- **Sleep:**
557
-
558
- ```json
559
- {
560
- "type": "sleep",
561
- "options": { "milliseconds": 5000 }
257
+ "options": { "flow": "flow-uuid", "payload": { "data": "{{ transform_result }}" }, "iterationMode": "parallel" }
562
258
  }
563
259
  ```
564
260
 
565
- **Log:**
261
+ **sleep/log/throw-error** - Utilities
566
262
 
567
263
  ```json
568
- {
569
- "type": "log",
570
- "options": { "message": "Processing item: {{ $trigger.payload.id }}" }
571
- }
264
+ {"type": "sleep", "options": {"milliseconds": 5000}}
265
+ {"type": "log", "options": {"message": "Processing {{ $trigger.payload.id }}"}}
266
+ {"type": "throw-error", "options": {"code": "CUSTOM_ERROR", "status": "400", "message": "Invalid data"}}
572
267
  ```
573
268
 
574
- **Throw Error:**
575
-
576
- ```json
577
- {
578
- "type": "throw-error",
579
- "options": {
580
- "code": "CUSTOM_ERROR",
581
- "status": "400",
582
- "message": "Invalid data: {{ $trigger.payload.error_details }}"
583
- }
584
- }
585
- ```
586
-
587
- </other_operations> </operation_examples>
588
-
589
- <data_chain_variables> Use `{{ variable }}` syntax to access data:
590
-
591
- - `{{ $trigger.payload }}` - Trigger data
592
- - `{{ $accountability.user }}` - User context
593
- - `{{ operation_key }}` - Result from specific operation (recommended)
594
- - `{{ operation_key.field }}` - Specific field from operation result
269
+ </operation_examples>
595
270
 
596
- **⚠️ Avoid `$last`:** While `{{ $last }}` references the previous operation's result, avoid using it in production
597
- flows. If you reorder operations, `$last` will reference a different operation, potentially breaking your flow. Always
598
- use specific operation keys like `{{ operation_key }}` for reliable, maintainable flows. </data_chain_variables>
271
+ <data_chain_variables> **Data Chain:** Use `{{ operation_key }}` to access results, `{{ $trigger.payload }}` for trigger
272
+ data. Avoid `{{ $last }}` (breaks when reordered). See `flows` tool for complete syntax. </data_chain_variables>
599
273
 
600
274
  <permission_options> For operations that support permissions:
601
275
 
@@ -604,118 +278,22 @@ use specific operation keys like `{{ operation_key }}` for reliable, maintainabl
604
278
  - `$full` - Use full system permissions
605
279
  - `role-uuid` - Use specific role's permissions </permission_options>
606
280
 
607
- <real_world_patterns> <data_processing_pipeline>
608
-
609
- ### Data Processing Pipeline
610
-
611
- Read → Transform → Update pattern:
612
-
613
- ```json
614
- // 1. Read with relations
615
- {
616
- "flow": "flow-uuid", "key": "invoice", "type": "item-read",
617
- "position_x": 19, "position_y": 1,
618
- "options": {
619
- "collection": "os_invoices",
620
- "key": ["{{$trigger.payload.invoice}}"],
621
- "query": {"fields": ["*", "line_items.*", "payments.*"]}
622
- },
623
- "resolve": "calc-operation-uuid"
624
- }
625
- // 2. Calculate totals
626
- {
627
- "flow": "flow-uuid", "key": "calculations", "type": "exec",
628
- "position_x": 37, "position_y": 1,
629
- "options": {
630
- "code": "module.exports = async function(data) {\n const invoice = data.invoice;\n const subtotal = invoice.line_items.reduce((sum, item) => sum + (item.price * item.quantity), 0);\n const tax = subtotal * 0.08;\n return { subtotal, tax, total: subtotal + tax };\n}"
631
- },
632
- "resolve": "update-operation-uuid"
633
- }
634
- // 3. Update with results
635
- {
636
- "flow": "flow-uuid", "key": "update_invoice", "type": "item-update",
637
- "position_x": 55, "position_y": 1,
638
- "options": {
639
- "collection": "os_invoices",
640
- "payload": "{{calculations}}",
641
- "key": ["{{$trigger.payload.invoice}}"]
642
- }
643
- }
644
- ```
645
-
646
- </data_processing_pipeline>
647
-
648
- <error_handling_branching>
649
-
650
- ### Error Handling with Branching
651
-
652
- ```json
653
- // Main operation with error handling
654
- {
655
- "flow": "flow-uuid", "key": "main_operation", "type": "request",
656
- "position_x": 19, "position_y": 1,
657
- "resolve": "success-operation-uuid",
658
- "reject": "error-operation-uuid"
659
- }
660
- // Success path
661
- {
662
- "flow": "flow-uuid", "key": "success_notification", "type": "notification",
663
- "position_x": 37, "position_y": 1
664
- }
665
- // Error path (lower row)
666
- {
667
- "flow": "flow-uuid", "key": "error_log", "type": "log",
668
- "position_x": 37, "position_y": 19
669
- }
670
- ```
671
-
672
- </error_handling_branching> </real_world_patterns>
673
-
674
281
  <common_mistakes>
675
282
 
676
- 1. **DO NOT** create operations without a flow - create flow first
677
- 2. **DO NOT** use operation keys in resolve/reject - use UUIDs (see <workflow_example> above)
678
- 3. **DO NOT** try to reference operations that do not exist yet
679
- 4. **DO NOT** use duplicate keys within the same flow
680
- 5. **DO NOT** create circular references in resolve/reject paths
681
- 6. **DO NOT** forget to handle both success and failure paths
682
- 7. **DO NOT** pass stringified JSON - use native objects (except request body)
683
- 8. **DO NOT** leave operations at default position (0,0) - see <positioning_system> above
684
- 9. **DO NOT** use dot notation in condition filters - see <critical_syntax> above
685
- 10. **DO NOT** use wrong format for request operations - see <critical_syntax> above </common_mistakes>
283
+ 1. Create flow first, never operations without flow
284
+ 2. Use UUIDs in resolve/reject, NOT keys
285
+ 3. Create operations before referencing them
286
+ 4. No duplicate keys within same flow
287
+ 5. Avoid circular resolve/reject references
288
+ 6. Set positions (not 0,0)
289
+ 7. Use nested objects in filters, NOT dot notation
290
+ 8. Request headers as array of objects, body as stringified JSON
291
+ 9. Pass native objects in data (except request body)
292
+ 10. ALWAYS pass native objects in data (EXCEPTIONS: - request body for `request` operation - code in `exec` operations)
293
+ 11. No `$NOW` variable - use exec operation: `return { now: new Date().toISOString() };` </common_mistakes>
686
294
 
687
295
  <troubleshooting>
688
- <invalid_foreign_key>
689
- ### "Invalid foreign key" Errors
690
-
691
- This typically means you're trying to reference an operation that doesn't exist:
692
-
693
- - Verify the operation UUID exists by reading operations for the flow
694
- - Check that you're using UUIDs (36 characters) not keys (short names)
695
- - Ensure operations are created before being referenced </invalid_foreign_key>
696
-
697
- <operation_not_executing>
698
-
699
- ### Operation Not Executing
700
-
701
- - Check the resolve/reject chain for breaks
702
- - Verify the first operation is set as the flow's `operation` field
703
- - Confirm all required operation options are provided </operation_not_executing>
704
-
705
- <overlapping_operations>
706
-
707
- ### Overlapping Operations in Visual Editor
708
-
709
- If operations appear stacked at (0,0) in the flow editor:
710
-
711
- ```json
712
- // Fix by updating each operation's position
713
- {"action": "update", "key": "operation-uuid", "data": {
714
- "position_x": 19, "position_y": 1
715
- }}
716
- {"action": "update", "key": "other-operation-uuid", "data": {
717
- "position_x": 37, "position_y": 1
718
- }}
719
- ```
720
-
721
- </overlapping_operations> </troubleshooting>
296
+ **Invalid foreign key:** Operation UUID doesn't exist. Use UUIDs (36 chars), not keys. Create operations before referencing.
297
+ **Not executing:** Check resolve/reject chain, verify flow.operation set, confirm required options provided.
298
+ **Overlapping (0,0):** Update positions: `{"action": "update", "key": "uuid", "data": {"position_x": 19, "position_y": 1}}`
299
+ </troubleshooting>
@@ -74,6 +74,11 @@ export const respond = asyncHandler(async (req, res) => {
74
74
  res.set('Content-Type', 'text/csv');
75
75
  return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'csv'));
76
76
  }
77
+ if (req.sanitizedQuery.export === 'csv_utf8') {
78
+ res.attachment(`${filename}.csv`);
79
+ res.set('Content-Type', 'text/csv; charset=utf-8');
80
+ return res.status(200).send(exportService.transform(res.locals['payload']?.data, 'csv_utf8'));
81
+ }
77
82
  if (req.sanitizedQuery.export === 'yaml') {
78
83
  res.attachment(`${filename}.yaml`);
79
84
  res.set('Content-Type', 'text/yaml');
@@ -96,9 +96,9 @@ export async function getQuery(rawQuery, schema, selections, variableValues, acc
96
96
  query.deep = replaceFuncs(query.deep);
97
97
  if (collection) {
98
98
  if (query.filter) {
99
- query.filter = filterReplaceM2A(query.filter, collection, schema);
99
+ query.filter = filterReplaceM2A(query.filter, collection, schema, { aliasMap: query.alias });
100
100
  }
101
- query.deep = filterReplaceM2ADeep(query.deep, collection, schema);
101
+ query.deep = filterReplaceM2ADeep(query.deep, collection, schema, { aliasMap: query.alias });
102
102
  }
103
103
  validateQuery(query);
104
104
  return query;
@@ -1,3 +1,7 @@
1
- import type { Filter, NestedDeepQuery, SchemaOverview } from '@directus/types';
2
- export declare function filterReplaceM2A(filter_arg: Filter, collection: string, schema: SchemaOverview): any;
3
- export declare function filterReplaceM2ADeep(deep_arg: NestedDeepQuery | null | undefined, collection: string, schema: SchemaOverview): any;
1
+ import type { Filter, NestedDeepQuery, Query, SchemaOverview } from '@directus/types';
2
+ export declare function filterReplaceM2A(filter_arg: Filter, collection: string, schema: SchemaOverview, options?: {
3
+ aliasMap?: Query['alias'];
4
+ }): any;
5
+ export declare function filterReplaceM2ADeep(deep_arg: NestedDeepQuery | null | undefined, collection: string, schema: SchemaOverview, options?: {
6
+ aliasMap?: Query['alias'];
7
+ }): any;