From 567fd127a36d818407e386da3074e43f0ebcc50f Mon Sep 17 00:00:00 2001 From: Gaetan SENN Date: Fri, 7 Nov 2025 19:19:29 +0100 Subject: [PATCH 1/4] feat: update swagger --- openapi/components/parameters.yaml | 103 +++++++++++++++++- openapi/index.yaml | 2 - .../items/_collection/getCollectionItems.yaml | 28 ++++- .../_collection/singleton/getSingleton.yaml | 47 -------- .../items/_collection/singleton/index.yaml | 4 - .../singleton/updateSingleton.yaml | 48 -------- .../paths/items/_collection/updateItems.yaml | 46 +++++--- 7 files changed, 152 insertions(+), 126 deletions(-) delete mode 100644 openapi/paths/items/_collection/singleton/getSingleton.yaml delete mode 100644 openapi/paths/items/_collection/singleton/index.yaml delete mode 100644 openapi/paths/items/_collection/singleton/updateSingleton.yaml diff --git a/openapi/components/parameters.yaml b/openapi/components/parameters.yaml index 53edd18..d9d453c 100644 --- a/openapi/components/parameters.yaml +++ b/openapi/components/parameters.yaml @@ -109,11 +109,110 @@ Version: schema: type: string Backlink: + description: Retrieve relational items excluding reverse relations when using wildcard fields. name: backlink - description: >- - Retrieve relational items excluding reverse relations when using wildcard fields. in: query required: false schema: type: boolean default: true +Aggregate: + description: Aggregate functions allow you to perform calculations on a set of values. Accepts one or more of `count`, `countDistinct`, `countAll`, `sum`, `sumDistinct`, `avg`, `avgDistinct`, `min`, `max`. + name: aggregate + in: query + required: false + content: + application/json: + schema: + type: object + properties: + count: + type: array + items: + type: string + description: Count the number of items. Use `['*']` to count all items. + countDistinct: + type: array + items: + type: string + description: Count the number of unique values in the specified fields. + countAll: + type: array + items: + type: string + description: Count all items including related items (used with groupBy). + sum: + type: array + items: + type: string + description: Sum the values of the specified fields. + sumDistinct: + type: array + items: + type: string + description: Sum the unique values of the specified fields. + avg: + type: array + items: + type: string + description: Calculate the average of the specified fields. + avgDistinct: + type: array + items: + type: string + description: Calculate the average of unique values in the specified fields. + min: + type: array + items: + type: string + description: Find the minimum value of the specified fields. + max: + type: array + items: + type: string + description: Find the maximum value of the specified fields. + example: + count: ['*'] + sum: ['price'] + avg: ['rating'] +Deep: + description: Deep allows you to set any of the other query parameters on a nested relational dataset. + name: deep + in: query + required: false + content: + application/json: + schema: + type: object + example: + related_articles: + _limit: 3 +Alias: + description: Alias allows you to rename fields in the response payload. + name: alias + in: query + required: false + content: + application/json: + schema: + type: object + example: + new_field_name: original_field_name +Group: + description: Grouping allows for running the aggregation functions based on a shared value. Accepts an array of field names. + name: group + in: query + required: false + explode: false + schema: + type: array + items: + type: string +VersionRaw: + description: Retrieve the raw delta of a Content Version item instead of the full merged item. + name: versionRaw + in: query + required: false + schema: + type: boolean + default: false diff --git a/openapi/index.yaml b/openapi/index.yaml index 50d1b15..e0cd814 100644 --- a/openapi/index.yaml +++ b/openapi/index.yaml @@ -83,8 +83,6 @@ paths: $ref: paths/items/_collection/index.yaml "/items/{collection}‎": $ref: paths/items/_collection/singular/index.yaml - "/items/{collection}/singleton": - $ref: paths/items/_collection/singleton/index.yaml "/items/{collection}/{id}": $ref: paths/items/_collection/_id/index.yaml "/metrics": diff --git a/openapi/paths/items/_collection/getCollectionItems.yaml b/openapi/paths/items/_collection/getCollectionItems.yaml index 92f802b..02005a1 100644 --- a/openapi/paths/items/_collection/getCollectionItems.yaml +++ b/openapi/paths/items/_collection/getCollectionItems.yaml @@ -1,5 +1,5 @@ -summary: List all items in a collection -description: Returns a list of the items in the given collection. +summary: Retrieve items in a collection +description: List all items in a collection or retrieve the plain singleton item. operationId: getCollectionItems parameters: - description: Unique identifier of the collection the item resides in. @@ -11,11 +11,19 @@ parameters: - $ref: ../../../components/parameters.yaml#/Fields - $ref: ../../../components/parameters.yaml#/Limit - $ref: ../../../components/parameters.yaml#/Offset +- $ref: ../../../components/parameters.yaml#/Page - $ref: ../../../components/parameters.yaml#/Meta - $ref: ../../../components/parameters.yaml#/Sort - $ref: ../../../components/parameters.yaml#/Filter - $ref: ../../../components/parameters.yaml#/Search +- $ref: ../../../components/parameters.yaml#/Export +- $ref: ../../../components/parameters.yaml#/Version +- $ref: ../../../components/parameters.yaml#/VersionRaw - $ref: ../../../components/parameters.yaml#/Backlink +- $ref: ../../../components/parameters.yaml#/Aggregate +- $ref: ../../../components/parameters.yaml#/Group +- $ref: ../../../components/parameters.yaml#/Deep +- $ref: ../../../components/parameters.yaml#/Alias responses: '200': description: Successful request @@ -25,9 +33,11 @@ responses: type: object properties: data: - type: array - items: - $ref: ../../../components/schemas/items.yaml + oneOf: + - type: array + items: + $ref: ../../../components/schemas/items.yaml + - $ref: ../../../components/schemas/items.yaml '401': $ref: ../../../components/responses.yaml#/UnauthorizedError '404': @@ -39,14 +49,20 @@ x-codeSamples: - label: Directus SDK lang: JavaScript source: | - import { createDirectus, rest, readItems } from '@directus/sdk'; + import { createDirectus, rest, readItems, readSingleton } from '@directus/sdk'; const client = createDirectus('directus_project_url').with(rest()); const result = await client.request(readItems('collection_name', query_object)); + + const singleton = await client.request(readSingleton('collection_name')); - label: GraphQL lang: GraphQL source: | type Query { + # For regular collections (returns array) : [] + + # For singleton collections (returns single object) + (version: String): } diff --git a/openapi/paths/items/_collection/singleton/getSingleton.yaml b/openapi/paths/items/_collection/singleton/getSingleton.yaml deleted file mode 100644 index b21c6c3..0000000 --- a/openapi/paths/items/_collection/singleton/getSingleton.yaml +++ /dev/null @@ -1,47 +0,0 @@ -summary: Retrieve a Singleton -description: | - Retrieves a singleton of a given collection. - - The REST and GraphQL requests for singletons are the same as those used to Get Items but in contrast the response consists of a plain item object (the singleton) instead of an array of items. -operationId: getSingleton -parameters: -- $ref: ../../../../components/parameters.yaml#/Collection -- $ref: ../../../../components/parameters.yaml#/Version -- $ref: ../../../../components/parameters.yaml#/Fields -- $ref: ../../../../components/parameters.yaml#/Meta -responses: - '200': - description: Successful request - content: - application/json: - schema: - type: object - properties: - data: - $ref: ../../../../components/schemas/items.yaml - '401': - $ref: ../../../../components/responses.yaml#/UnauthorizedError - '404': - $ref: ../../../../components/responses.yaml#/NotFoundError -security: [] -tags: -- Items -x-codeSamples: - - label: Directus SDK - lang: JavaScript - source: | - import { createDirectus, rest, readSingleton } from '@directus/sdk'; - - const client = createDirectus('directus_project_url').with(rest()); - - const result = await client.request(readSingleton(collection_name)); - - label: GraphQL - lang: GraphQL - source: | - type Query { - (version: String): - } - - type Query { - _by_version(version: String!): - } diff --git a/openapi/paths/items/_collection/singleton/index.yaml b/openapi/paths/items/_collection/singleton/index.yaml deleted file mode 100644 index 5a46688..0000000 --- a/openapi/paths/items/_collection/singleton/index.yaml +++ /dev/null @@ -1,4 +0,0 @@ -get: - $ref: getSingleton.yaml -patch: - $ref: updateSingleton.yaml diff --git a/openapi/paths/items/_collection/singleton/updateSingleton.yaml b/openapi/paths/items/_collection/singleton/updateSingleton.yaml deleted file mode 100644 index 8993ee6..0000000 --- a/openapi/paths/items/_collection/singleton/updateSingleton.yaml +++ /dev/null @@ -1,48 +0,0 @@ -summary: Update Singleton -description: | - Update a singleton item. - - The REST and GraphQL requests for singletons are the same as those used to Update Multiple Items but in contrast the request should consist of the plain item object. -operationId: updateSingleton -parameters: -- $ref: ../../../../components/parameters.yaml#/Collection -- $ref: ../../../../components/parameters.yaml#/Fields -- $ref: ../../../../components/parameters.yaml#/Meta -requestBody: - content: - application/json: - schema: - anyOf: - - $ref: ../../../../components/schemas/items.yaml -responses: - '200': - description: Successful request - content: - application/json: - schema: - type: object - properties: - data: - $ref: ../../../../components/schemas/items.yaml - '401': - $ref: ../../../../components/responses.yaml#/UnauthorizedError - '404': - $ref: ../../../../components/responses.yaml#/NotFoundError -security: [] -tags: -- Items -x-codeSamples: -- label: Directus SDK - lang: JavaScript - source: | - import { createDirectus, rest, updateSingleton } from '@directus/sdk'; - - const client = createDirectus('directus_project_url').with(rest()); - - const result = await client.request(updateSingleton(collection_name, partial_item_object)); -- label: GraphQL - lang: GraphQL - source: | - type Mutation { - update__items(data: [update__input]): [] - } diff --git a/openapi/paths/items/_collection/updateItems.yaml b/openapi/paths/items/_collection/updateItems.yaml index c47becb..65d0648 100644 --- a/openapi/paths/items/_collection/updateItems.yaml +++ b/openapi/paths/items/_collection/updateItems.yaml @@ -1,6 +1,6 @@ -summary: Update Multiple Items -description: Update multiple items at the same time. +summary: Update Items +description: Update multiple items in a collection or update the singleton item. operationId: updateItems parameters: - $ref: ../../../components/parameters.yaml#/Collection @@ -15,17 +15,21 @@ requestBody: content: application/json: schema: - type: object - required: - - data - - keys - properties: - data: - $ref: ../../../components/schemas/items.yaml - keys: - type: array - items: - type: string + oneOf: + - type: object + description: Update multiple items (regular collections) + required: + - data + - keys + properties: + data: + $ref: ../../../components/schemas/items.yaml + keys: + type: array + items: + type: string + - $ref: ../../../components/schemas/items.yaml + description: Update single item (singleton collections) responses: '200': description: Successful request @@ -35,9 +39,13 @@ responses: type: object properties: data: - type: array - items: - $ref: ../../../components/schemas/items.yaml + oneOf: + - type: array + items: + $ref: ../../../components/schemas/items.yaml + description: Array of updated items + - $ref: ../../../components/schemas/items.yaml + description: Singleton updated item meta: $ref: ../../../components/schemas/x-metadata.yaml '401': @@ -51,11 +59,15 @@ x-codeSamples: - label: Directus SDK lang: JavaScript source: | - import { createDirectus, rest, updateItems } from '@directus/sdk'; + import { createDirectus, rest, updateItems, updateSingleton } from '@directus/sdk'; const client = createDirectus('directus_project_url').with(rest()); + // For regular collections const result = await client.request(updateItems(collection_name, item_id_array, partial_item_object)); + + // For singleton collections + const singleton = await client.request(updateSingleton(collection_name, partial_item_object)); - label: GraphQL lang: GraphQL source: | From e09141aa1002f6b9543ae09278a3332ddbd26634 Mon Sep 17 00:00:00 2001 From: Gaetan SENN Date: Fri, 7 Nov 2025 19:30:35 +0100 Subject: [PATCH 2/4] fix: fix format --- openapi/components/parameters.yaml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/openapi/components/parameters.yaml b/openapi/components/parameters.yaml index d9d453c..7a7e6bb 100644 --- a/openapi/components/parameters.yaml +++ b/openapi/components/parameters.yaml @@ -102,14 +102,14 @@ Export: - yaml Version: name: version - description: >- - Retrieve an item's state from a specific Content Version. The value corresponds to the "key" of the Content Version. + description: Retrieve an item's state from a specific Content Version. The value corresponds to the "key" of the Content Version. in: query required: false schema: type: string Backlink: - description: Retrieve relational items excluding reverse relations when using wildcard fields. + description: >- + Retrieve relational items excluding reverse relations when using wildcard fields. name: backlink in: query required: false @@ -117,7 +117,8 @@ Backlink: type: boolean default: true Aggregate: - description: Aggregate functions allow you to perform calculations on a set of values. Accepts one or more of `count`, `countDistinct`, `countAll`, `sum`, `sumDistinct`, `avg`, `avgDistinct`, `min`, `max`. + description: >- + Aggregate functions allow you to perform calculations on a set of values. Accepts one or more of `count`, `countDistinct`, `countAll`, `sum`, `sumDistinct`, `avg`, `avgDistinct`, `min`, `max`. name: aggregate in: query required: false @@ -176,7 +177,8 @@ Aggregate: sum: ['price'] avg: ['rating'] Deep: - description: Deep allows you to set any of the other query parameters on a nested relational dataset. + description: >- + Deep allows you to set any of the other query parameters on a nested relational dataset. name: deep in: query required: false @@ -199,7 +201,8 @@ Alias: example: new_field_name: original_field_name Group: - description: Grouping allows for running the aggregation functions based on a shared value. Accepts an array of field names. + description: >- + Grouping allows for running the aggregation functions based on a shared value. Accepts an array of field names. name: group in: query required: false From 18174cacb9bb0aadd66a468bc039fa0ee866d96f Mon Sep 17 00:00:00 2001 From: Gaetan SENN Date: Fri, 7 Nov 2025 19:36:36 +0100 Subject: [PATCH 3/4] feat: optimize params --- openapi/components/parameters.yaml | 42 +++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/openapi/components/parameters.yaml b/openapi/components/parameters.yaml index 7a7e6bb..5d469da 100644 --- a/openapi/components/parameters.yaml +++ b/openapi/components/parameters.yaml @@ -177,8 +177,7 @@ Aggregate: sum: ['price'] avg: ['rating'] Deep: - description: >- - Deep allows you to set any of the other query parameters on a nested relational dataset. + description: Deep allows you to set any of the other query parameters on a nested relational dataset. Use underscore-prefixed parameter names. name: deep in: query required: false @@ -186,11 +185,43 @@ Deep: application/json: schema: type: object + additionalProperties: + type: object + description: Query parameters for the related field (prefixed with underscore). + properties: + _fields: + type: array + items: + type: string + _sort: + type: array + items: + type: string + _filter: + type: object + _limit: + type: integer + _offset: + type: integer + _page: + type: integer + _search: + type: string + _group: + type: array + items: + type: string + _aggregate: + type: object example: related_articles: _limit: 3 + _sort: ['-date_created'] + _filter: + status: + _eq: 'published' Alias: - description: Alias allows you to rename fields in the response payload. + description: Alias allows you to rename fields in the response payload. The key is the new name, the value is the original field name. name: alias in: query required: false @@ -198,8 +229,11 @@ Alias: application/json: schema: type: object + additionalProperties: + type: string example: - new_field_name: original_field_name + display_name: full_name + creation_date: date_created Group: description: >- Grouping allows for running the aggregation functions based on a shared value. Accepts an array of field names. From c6eff505c27861ca82a2163f3e1d418abef499cc Mon Sep 17 00:00:00 2001 From: Gaetan SENN Date: Fri, 7 Nov 2025 19:42:55 +0100 Subject: [PATCH 4/4] fix: add missing graphQL singleton update --- openapi/paths/items/_collection/updateItems.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openapi/paths/items/_collection/updateItems.yaml b/openapi/paths/items/_collection/updateItems.yaml index 65d0648..baa18c5 100644 --- a/openapi/paths/items/_collection/updateItems.yaml +++ b/openapi/paths/items/_collection/updateItems.yaml @@ -72,5 +72,9 @@ x-codeSamples: lang: GraphQL source: | type Mutation { - update__items(ids: [ID!]!, data: [update__input]): [] + # For regular collections + update__items(ids: [ID!]!, data: update__input!): [] + + # For singleton collections + update_(data: update__input!): }