Files
directus/docs/reference/system/versions.md
ian 189fcb24f7 Reduce dependencies on activity and revisions tables (#23612)
* Extract comments to a separate table (#22295)

* Add directus_comments migration

* Add comments controller and service

* Remove from activity

* Update system-data and types

* Refactor app with new endpoints

* Expose service

* Update app minimal permissions

* Add collection translation

* Define relations

* Allow comment creation only if there's item read access

* Patch for MSSQL double constraints issue

* Fix users service test

* Add sdk support

* Update specs

* Fix formatting

* Fix specs error

* Patch whoopsie

* Remove obsolete GraphQL mutations

* Update required fields

* Remove unused vars

* Allow edit and delete of legacy activity comments

* Remove legacy comments from SDK

* Add changeset

* Batch upwards migration

* Update SDK to use keysOrQuery

Co-authored-by: Brainslug <br41nslug@users.noreply.github.com>

* Update implementation for keysOrQuery

* Remove singleton check

* Update SDK to use keysOrQuery 2

Co-authored-by: Brainslug <br41nslug@users.noreply.github.com>

* Update keysOrQuery typedoc

* Fix import

* Update migration timestamp

* fixed import

* Update api/src/utils/get-service.ts

* utilize chunk processing in migration

* formatting

* only services extended from itemservice should be added

* remove redundant checks from comment header

* update comment service to v11 permission format

* specify missing required fields

* Mock comments in users test

* Simplify migration and update date

* WIP legacy access

* Optimise imports

* WIP app cleanup

* Update loadUserPreviews typing

Co-authored-by: Daniel Biegler <DanielBiegler@users.noreply.github.com>

* Read legacy comments

* Parse using comments service

* Perform migration directly

* Fix legacy app sort query which uses id

* Migrate legacy comments in mutations

* Reduce api semver

* Update app recommended permissions

* Recommend updating of comment only

* replace hardcoded type with existing one

* Allow users to update or delete their own comments

Co-authored-by: daedalus <44623501+ComfortablyCoding@users.noreply.github.com>

* Skip further access validation for non-existent collections

* Check if collection exists before the admin check

Co-authored-by: daedalus <44623501+ComfortablyCoding@users.noreply.github.com>

* Fix incorrect legacy check

Co-authored-by: Daniel Biegler <DanielBiegler@users.noreply.github.com>

* Fix merging of count when db returns count as string type

* Remove unused import

---------

Co-authored-by: Brainslug <br41nslug@users.noreply.github.com>
Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
Co-authored-by: Brainslug <tim@brainslug.nl>
Co-authored-by: daedalus <44623501+ComfortablyCoding@users.noreply.github.com>
Co-authored-by: Daniel Biegler <DanielBiegler@users.noreply.github.com>

* Consolidate content versioning (#22413)

* Add migration

* Use the new delta field

* Add cast-json flag

* Fix typing

* Fetch existing deltas if version created during migration

* Add changeset

* Add version delta field into sdk schema

* Update migration timestamp

* Update versions.save() to return finalVersionDelta

Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>

* Sort on DB level

* Update migration date

* Disallow passing delta via create/update

* Update docs & specs

* Fix save response

* Remove unnecessary access check

Already checked by the subsequent itemsService.readOne call

* Update changeset

* Don't require update perms on versions for save

* Optimize validateCreateData

* update to new validateAccess

* Update docs/reference/system/versions.md

* Remove migration of delta

* Rename to legacy

* Add missed changes for Remove migration of delta in 2e2f50fa67

* Update docs/reference/system/versions.md

---------

Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
Co-authored-by: daedalus <44623501+ComfortablyCoding@users.noreply.github.com>

* Update migration dates

* api change should be major for versioning

* Remove comment paths from activity reference

* Added comments reference

* Added directus_comments to table of system collections

* The linter demands newline

* Revert function renaming for patch semver

* Use transaction in down migration for comments (#23715)

---------

Co-authored-by: Brainslug <br41nslug@users.noreply.github.com>
Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
Co-authored-by: Brainslug <tim@brainslug.nl>
Co-authored-by: daedalus <44623501+ComfortablyCoding@users.noreply.github.com>
Co-authored-by: Daniel Biegler <DanielBiegler@users.noreply.github.com>
Co-authored-by: Kevin Lewis <kvn@lws.io>
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
2024-10-16 09:33:11 -04:00

20 KiB

description, readTime, pageClass
description readTime pageClass
REST and GraphQL API documentation on the Versions collection in Directus. 5 min read page-reference

Content Versions

Content Versioning enables users to create unpublished copies of an item (called "Content Versions"), modify them independently from the main version, and promote them to become the new main version when ready.

The Content Version Object

id uuid
Primary key of the Content Version.

key string
Key of the Content Version, used as the value for the version query parameter.

name string
Descriptive name of the Content Version.

collection string
Name of the collection the Content Version is created on.

item many-to-one
The item the Content Version is created on.

date_created Date
When the Content Version was created.

date_updated Date
When the Content Version was last updated.

user_created many-to-one
User that created the Content Version. Many-to-one to users.

user_updated many-to-one
User that last updated the Content Version. Many-to-one to users.

delta json
The current changes compared to the main version of the item.

{
	"id": "21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5",
	"key": "my_version",
	"name": "My Version",
	"collection": "my_collection",
	"item": "1",
	"hash": "aaafc0db8fb60e82e634903523e1fa2144c58520",
	"date_created": "2024-07-22T10:33:02.542Z",
	"date_updated": "2024-07-22T10:33:14.324Z",
	"user_created": "a2dbc923-7c75-4d26-83f4-4674bfa7be81",
	"user_updated": "a2dbc923-7c75-4d26-83f4-4674bfa7be81",
	"delta": {
		"my_field": "Updated Value"
	}
}

List Content Versions

List all Content Versions that exist in Directus.

Request

GET /versions

SEARCH /versions

If using SEARCH you can provide a query object as the body of your request.

Learn more about SEARCH ->

POST /graphql/system

type Query {
	versions: [directus_versions]
}
import { createDirectus, rest, readContentVersions } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(readContentVersions(query_object));

Query Parameters

Supports all global query parameters.

Response

An array of up to limit Content Version objects. If no items are available, data will be an empty array.

Example

GET /versions

SEARCH /versions

POST /graphql/system

query {
	versions {
		id
		key
		name
	}
}
import { createDirectus, rest, readContentVersions } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	readContentVersions({
		fields: ['*'],
	})
);

Retrieve a Content Version

List an existing Content Version by primary key.

Request

GET /versions/:id

POST /graphql/system

type Query {
	versions_by_id(id: ID!): directus_versions
}
import { createDirectus, rest, readContentVersion } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(readContentVersion(content_version_id, query_object));

Query Parameters

Supports all global query parameters.

Response

Returns the requested Content Version object.

Example

GET /versions/21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5

POST /graphql/system

query {
	versions_by_id(id: "e35f7b9a-aabe-4a41-92b4-2bed97fd49ef") {
		id
		key
		name
	}
}
import { createDirectus, rest, readContentVersion } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	readContentVersion('dc2ac3f9-2076-4e86-8677-b47643eddacf', {
		fields: ['*'],
	})
);

Create a Content Version

Create a new Content Version for an item.

Request

POST /versions

Provide a Content Version object as the body of your request.

POST /graphql/system

type Mutation {
	create_versions_item(data: create_directus_versions_input!): directus_versions
}
import { createDirectus, rest, createContentVersion } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(createContentVersion(content_version_object));

Query Parameters

Supports all global query parameters.

Request Body

A partial Content Version object.

Response

Returns the Content Version object for the created version.

Example

POST /versions

{
	"key": "my_version",
	"name": "My Version",
	"collection": "my_collection",
	"item": "1"
}

POST /graphql/system

mutation {
	create_versions_item(data: { key: "my_version", name: "My Version", collection: "my_collection", item: "1" }) {
		id
		key
		name
	}
}
import { createDirectus, rest, createContentVersion } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	createContentVersion({
		key: 'my_version',
		name: 'My Version',
		collection: 'my_collection',
		item: 1,
	})
);

Create Multiple Content Versions

Create multiple new Content Versions.

Request

POST /versions

Provide an array of Content Version objects as the body of your request.

POST /graphql/system

type Mutation {
	create_versions_items(data: [create_directus_versions_input!]!): [directus_versions]
}
import { createDirectus, rest, createContentVersions } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(createContentVersions(content_version_object_array));

Query Parameters

Supports all global query parameters.

Request Body

An array of partial Content Version objects.

Response

Returns an array of Content Version objects for the created versions.

Example

POST /versions

[
	{
		"key": "my_version",
		"name": "My Version",
		"collection": "my_collection",
		"item": 1
	},
	{
		"key": "another_version",
		"name": "Another Version",
		"collection": "another_collection",
		"item": 2
	}
]

POST /graphql/system

mutation {
	create_versions_items(
		data: [
			{ key: "my_version", name: "My Version", collection: "my_collection", item: "1" }
			{ key: "another_version", name: "Another Version", collection: "another_collection", item: "2" }
		]
	) {
		id
		key
		name
	}
}
import { createDirectus, rest, createContentVersions } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	createContentVersions([
		{
			key: 'my_version',
			name: 'My Version',
			collection: 'my_collection',
			item: 1,
		},
		{
			key: 'another_version',
			name: 'Another Version',
			collection: 'another_collection',
			item: 2,
		},
	])
);

Update a Content Version

Update an existing Content Version.

Request

PATCH /versions/:id

Provide a partial Content Version object as the body of your request.

POST /graphql/system

type Mutation {
	update_versions_item(id: ID!, data: update_directus_versions_input!): directus_versions
}
import { createDirectus, rest, updateContentVersion } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(updateContentVersion(content_version_id, partial_content_version_object));

Query Parameters

Supports all global query parameters.

Request Body

A partial Content Version object.

Response

Returns the Content Version object for the updated version.

Example

PATCH /versions/21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5

{
	"name": "My Updated Version"
}

POST /graphql/system

mutation {
	update_versions_item(id: "21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5", data: { name: "My Updated Version" }) {
		id
		key
		name
	}
}
import { createDirectus, rest, updateContentVersion } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	updateContentVersion('21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5', {
		name: 'My Updated Version',
	})
);

Update Multiple Content Versions

Update multiple existing Content Versions.

Request

PATCH /versions

{
	"keys": content_version_id_array,
	"data": partial_content_version_object
}

POST /graphql/system

type Mutation {
	update_versions_items(ids: [ID!]!, data: update_directus_versions_input!): [directus_versions]
}
import { createDirectus, rest, updateContentVersions } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(updateContentVersions(content_version_id_array, partial_content_version_object));

Query Parameters

Supports all global query parameters.

Request Body

keys Required
Array of primary keys of the Content Versions you'd like to update.

data Required
The name property of the Content Version object.

Response

Returns the Content Version objects for the updated versions.

Example

PATCH /versions

{
	"keys": ["21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5", "31e1c0c6-b575-47fb-908a-baf81b4e5631"],
	"data": {
		"name": "My Updated Version"
	}
}

POST /graphql/system

mutation {
	update_versions_items(
		ids: ["21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5", "31e1c0c6-b575-47fb-908a-baf81b4e5631"]
		data: { name: "My Updated Version" }
	) {
		id
		key
		name
	}
}
import { createDirectus, rest, updateContentVersions } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	updateContentVersions(['21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5', '31e1c0c6-b575-47fb-908a-baf81b4e5631'], {
		name: 'My Updated Version',
	})
);

Delete a Content Version

Delete an existing Content Version.

Request

DELETE /versions/:id

POST /graphql/system

type Mutation {
	delete_versions_item(id: ID!): delete_one
}
import { createDirectus, rest, deleteContentVersion } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(deleteContentVersion(content_version_id));

Response

Empty body.

Example

DELETE /versions/21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5

POST /graphql/system

mutation {
	delete_versions_item(id: "21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5") {
		id
	}
}
import { createDirectus, rest, deleteContentVersion } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(deleteContentVersion('21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5'));

Delete Multiple Content Versions

Delete multiple existing Content Versions.

Request

DELETE /versions

Provide an array of Content Version IDs as the body of your request.

POST /graphql/system

type Mutation {
	delete_versions_items(ids: [ID!]!): delete_many
}
import { createDirectus, rest, deleteContentVersions } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(deleteContentVersions(content_version_id_array));

Request Body

An array of Content Version primary keys

Response

Empty body.

Example

DELETE /versions

["21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5", "31e1c0c6-b575-47fb-908a-baf81b4e5631"]

POST /graphql/system

mutation {
	delete_versions_items(ids: ["21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5", "31e1c0c6-b575-47fb-908a-baf81b4e5631"]) {
		ids
	}
}
import { createDirectus, rest, deleteContentVersions } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	deleteContentVersions(['21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5', '31e1c0c6-b575-47fb-908a-baf81b4e5631'])
);

Save to a Content Version

Save item changes to an existing Content Version.

Request

POST /versions/:id/save

Provide a partial item object as the body of your request.

// Not supported in GraphQL
import { createDirectus, rest, saveToContentVersion } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(saveToContentVersion(content_version_id, partial_item_object));

Response

Returns the item object with the new state after save.

Example

POST /versions/21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5/save

{
	"my_field": "Updated Value"
}
// Not supported in GraphQL
import { createDirectus, rest, saveContentVersion } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	saveContentVersion('21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5', { my_field: 'Updated Value' })
);

Compare a Content Version

Compare an existing Content Version with the main version of the item.

Request

GET /versions/:id/compare

// Not supported in GraphQL
import { createDirectus, rest, compareContentVersion } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(compareContentVersion(content_version_id));

Response

Returns all fields with different values, along with the hash of the main version of the item and the information whether the Content Version is outdated (i.e. main version of the item has been updated since the creation of the Content Version):

{
	"outdated": false,
	"mainHash": "2ee9c4e33b19d2cdec66a1ff7355e75a331591d9",
	"current": {
		"my_field": "Updated Value"
	},
	"main": {
		"my_field": "Main Value"
	}
}

Example

GET /versions/21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5/compare

// Not supported in GraphQL
import { createDirectus, rest, compareContentVersion } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(compareContentVersion('21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5'));

Promote a Content Version

Promote an existing Content Version to become the new main version of the item.

Request

POST /versions/:id/promote

Pass the current hash of the main version of the item (obtained from the compare endpoint) along with an optional array of field names of which the values are to be promoted (by default, all fields are selected).

{
	"mainHash": main_hash,
	"fields": fields_name_array
}
// Not supported in GraphQL
import { createDirectus, rest, promoteContentVersion } from '@directus/sdk';

const client = createDirectus('directus_project_url').with(rest());

const result = await client.request(promoteContentVersion(content_version_id, promote_object));

Response

The primary key of the promoted item.

Example

POST /versions/21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5/promote

{
	"mainHash": "2ee9c4e33b19d2cdec66a1ff7355e75a331591d9",
	"fields": ["my_field"]
}
// Not supported in GraphQL
import { createDirectus, rest, promoteContentVersion } from '@directus/sdk';

const client = createDirectus('https://directus.example.com').with(rest());

const result = await client.request(
	promoteContentVersion('21a7ed5f-eb19-42ae-8ee2-61f25b8c4eb5', '2ee9c4e33b19d2cdec66a1ff7355e75a331591d9', [
		'my_field',
	])
);