From e56c6a36abc3a34501417600668826917435901f Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Wed, 29 Jan 2025 14:58:24 +0100
Subject: [PATCH 01/31] GO-4459: Add descriptions for swagger data models
---
core/api/docs/docs.go | 207 ++++++++++++++++++++---
core/api/docs/swagger.json | 207 ++++++++++++++++++++---
core/api/docs/swagger.yaml | 172 ++++++++++++++++---
core/api/internal/auth/model.go | 6 +-
core/api/internal/export/model.go | 4 +-
core/api/internal/object/model.go | 112 ++++++------
core/api/internal/object/service_test.go | 9 +-
core/api/internal/search/model.go | 10 +-
core/api/internal/space/model.go | 56 +++---
core/api/pagination/model.go | 12 +-
10 files changed, 614 insertions(+), 181 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 838673118d..34e2a56f64 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -947,6 +947,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"challenge_id": {
+ "description": "The challenge id associated with the displayed code and needed to solve the challenge for token",
"type": "string",
"example": "67647f5ecda913e9a2e11b26"
}
@@ -956,10 +957,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"app_key": {
+ "description": "The permanent app key",
"type": "string",
"example": "zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="
},
"session_token": {
+ "description": "The ephemeral session token",
"type": "string",
"example": "eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"
}
@@ -969,6 +972,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"path": {
+ "description": "The path the object was exported to",
"type": "string",
"example": "/path/to/export"
}
@@ -978,6 +982,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"align": {
+ "description": "The alignment of the block",
"type": "string",
"enum": [
"AlignLeft",
@@ -988,10 +993,12 @@ const docTemplate = `{
"example": "AlignLeft"
},
"background_color": {
+ "description": "The background color of the block",
"type": "string",
"example": "red"
},
"children_ids": {
+ "description": "The ids of the block's children",
"type": "array",
"items": {
"type": "string"
@@ -1001,16 +1008,28 @@ const docTemplate = `{
]
},
"file": {
- "$ref": "#/definitions/object.File"
+ "description": "The file of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.File"
+ }
+ ]
},
"id": {
+ "description": "The id of the block",
"type": "string",
"example": "64394517de52ad5acb89c66c"
},
"text": {
- "$ref": "#/definitions/object.Text"
+ "description": "The text of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Text"
+ }
+ ]
},
"vertical_align": {
+ "description": "The vertical alignment of the block",
"type": "string",
"enum": [
"VerticalAlignTop",
@@ -1025,30 +1044,37 @@ const docTemplate = `{
"type": "object",
"properties": {
"body": {
+ "description": "The body of the object",
"type": "string",
- "example": "Object Body"
+ "example": "This is the body of the object. Markdown syntax is supported here."
},
"description": {
+ "description": "The description of the object",
"type": "string",
- "example": "Object Description"
+ "example": "This is a description of the object."
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"object_type_unique_key": {
+ "description": "The unique key of the object type",
"type": "string",
"example": "ot-page"
},
"source": {
+ "description": "The source url, only applicable for bookmarks",
"type": "string",
- "example": "https://source.com"
+ "example": "https://bookmark-source.com"
},
"template_id": {
+ "description": "The id of the template to use",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
}
@@ -1058,10 +1084,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"details": {
+ "description": "The details",
"type": "object",
"additionalProperties": true
},
"id": {
+ "description": "The id of the detail",
"type": "string",
"enum": [
"last_modified_date",
@@ -1079,30 +1107,39 @@ const docTemplate = `{
"type": "object",
"properties": {
"added_at": {
+ "description": "The added at of the file",
"type": "integer"
},
"hash": {
+ "description": "The hash of the file",
"type": "string"
},
"mime": {
+ "description": "The mime of the file",
"type": "string"
},
"name": {
+ "description": "The name of the file",
"type": "string"
},
"size": {
+ "description": "The size of the file",
"type": "integer"
},
"state": {
+ "description": "The state of the file",
"type": "string"
},
"style": {
+ "description": "The style of the file",
"type": "string"
},
"target_object_id": {
+ "description": "The target object id of the file",
"type": "string"
},
"type": {
+ "description": "The type of the file",
"type": "string"
}
}
@@ -1111,46 +1148,56 @@ const docTemplate = `{
"type": "object",
"properties": {
"blocks": {
+ "description": "The blocks of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Block"
}
},
"details": {
+ "description": "The details of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Detail"
}
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the object",
"type": "string",
"example": "bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"
},
"layout": {
+ "description": "The layout of the object",
"type": "string",
"example": "basic"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"root_id": {
+ "description": "The id of the object's root",
"type": "string",
"example": "bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"
},
"snippet": {
+ "description": "The snippet of the object, especially important for notes as they don't have a name",
"type": "string",
"example": "The beginning of the object body..."
},
"space_id": {
+ "description": "The id of the space the object is in",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "Page"
}
@@ -1160,7 +1207,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"object": {
- "$ref": "#/definitions/object.Object"
+ "description": "The object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Object"
+ }
+ ]
}
}
},
@@ -1168,18 +1220,22 @@ const docTemplate = `{
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the template",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the template",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
},
"name": {
+ "description": "The name of the template",
"type": "string",
- "example": "Template Name"
+ "example": "My template"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "template"
}
@@ -1189,7 +1245,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"template": {
- "$ref": "#/definitions/object.Template"
+ "description": "The template",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Template"
+ }
+ ]
}
}
},
@@ -1197,18 +1258,22 @@ const docTemplate = `{
"type": "object",
"properties": {
"checked": {
+ "description": "Whether the text is checked",
"type": "boolean",
"example": true
},
"color": {
+ "description": "The color of the text",
"type": "string",
"example": "red"
},
"icon": {
+ "description": "The icon of the text",
"type": "string",
"example": "📄"
},
"style": {
+ "description": "The style of the text",
"type": "string",
"enum": [
"Paragraph",
@@ -1229,8 +1294,9 @@ const docTemplate = `{
"example": "Paragraph"
},
"text": {
+ "description": "The text",
"type": "string",
- "example": "Some text"
+ "example": "Some text..."
}
}
},
@@ -1238,26 +1304,32 @@ const docTemplate = `{
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the type",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the type",
"type": "string",
"example": "bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"
},
"name": {
+ "description": "The name of the type",
"type": "string",
"example": "Page"
},
"recommended_layout": {
+ "description": "The recommended layout of the type",
"type": "string",
"example": "todo"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "type"
},
"unique_key": {
+ "description": "The unique key of the type",
"type": "string",
"example": "ot-page"
}
@@ -1267,7 +1339,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"type": {
- "$ref": "#/definitions/object.Type"
+ "description": "The type",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Type"
+ }
+ ]
}
}
},
@@ -1275,13 +1352,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Object"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1289,13 +1372,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Template"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1303,13 +1392,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Type"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1317,13 +1412,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Member"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1331,13 +1432,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Space"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1345,22 +1452,22 @@ const docTemplate = `{
"type": "object",
"properties": {
"has_more": {
- "description": "whether there are more items available",
+ "description": "Indicates if there are more items available beyond the current result set",
"type": "boolean",
"example": true
},
"limit": {
- "description": "the current limit",
+ "description": "The maximum number of items returned in the result set",
"type": "integer",
"example": 100
},
"offset": {
- "description": "the current offset",
+ "description": "The number of items skipped before starting to collect the result set",
"type": "integer",
"example": 0
},
"total": {
- "description": "the total number of items available on that endpoint",
+ "description": "The total number of items available for the endpoint",
"type": "integer",
"example": 1024
}
@@ -1370,16 +1477,30 @@ const docTemplate = `{
"type": "object",
"properties": {
"query": {
- "type": "string"
+ "description": "The search term to look for in object names and snippets",
+ "type": "string",
+ "example": "test"
},
"sort": {
- "$ref": "#/definitions/search.SortOptions"
+ "description": "The sorting criteria and direction for the search results",
+ "allOf": [
+ {
+ "$ref": "#/definitions/search.SortOptions"
+ }
+ ]
},
"types": {
+ "description": "The types of objects to search for, specified by unique key or ID",
"type": "array",
"items": {
"type": "string"
- }
+ },
+ "example": [
+ "ot-note",
+ "ot-page",
+ "ot-678043f0cda9133be777049f",
+ "bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"
+ ]
}
}
},
@@ -1387,6 +1508,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"direction": {
+ "description": "The direction to sort the search results",
"type": "string",
"default": "desc",
"enum": [
@@ -1395,6 +1517,7 @@ const docTemplate = `{
]
},
"timestamp": {
+ "description": "The timestamp to sort the search results by",
"type": "string",
"default": "last_modified_date",
"enum": [
@@ -1409,6 +1532,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"name": {
+ "description": "The name of the space",
"type": "string",
"example": "New Space"
}
@@ -1418,7 +1542,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"space": {
- "$ref": "#/definitions/space.Space"
+ "description": "The created space",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Space"
+ }
+ ]
}
}
},
@@ -1426,26 +1555,32 @@ const docTemplate = `{
"type": "object",
"properties": {
"global_name": {
+ "description": "The global name of the member in the network",
"type": "string",
"example": "john.any"
},
"icon": {
+ "description": "The icon of the member",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"
},
"id": {
+ "description": "The profile object id of the member",
"type": "string",
"example": "_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"
},
"identity": {
+ "description": "The identity of the member in the network",
"type": "string",
"example": "AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"
},
"name": {
+ "description": "The name of the member",
"type": "string",
"example": "John Doe"
},
"role": {
+ "description": "The role of the member",
"type": "string",
"enum": [
"Reader",
@@ -1456,6 +1591,7 @@ const docTemplate = `{
"example": "Owner"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "member"
}
@@ -1465,78 +1601,97 @@ const docTemplate = `{
"type": "object",
"properties": {
"account_space_id": {
+ "description": "The id of the account space",
"type": "string",
"example": "bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"
},
"analytics_id": {
+ "description": "The analytics id of the account",
"type": "string",
"example": "624aecdd-4797-4611-9d61-a2ae5f53cf1c"
},
"archive_object_id": {
+ "description": "The id of the archive object",
"type": "string",
"example": "bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"
},
"device_id": {
+ "description": "The id of the device",
"type": "string",
"example": "12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"
},
"gateway_url": {
+ "description": "The gateway url to serve files and media",
"type": "string",
"example": "http://127.0.0.1:31006"
},
"home_object_id": {
+ "description": "The id of the home object",
"type": "string",
"example": "bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"
},
"icon": {
+ "description": "The icon of the space",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"
},
"id": {
+ "description": "The id of the space",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"local_storage_path": {
+ "description": "The local storage path of the account",
"type": "string",
"example": "/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"
},
"marketplace_workspace_id": {
+ "description": "The id of the marketplace workspace",
"type": "string",
"example": "_anytype_marketplace"
},
"name": {
+ "description": "The name of the space",
"type": "string",
- "example": "Space Name"
+ "example": "My Space"
},
"network_id": {
+ "description": "The network id of the space",
"type": "string",
"example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
},
"profile_object_id": {
+ "description": "The id of the profile object",
"type": "string",
"example": "bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"
},
"space_view_id": {
+ "description": "The id of the space view",
"type": "string",
"example": "bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"
},
"tech_space_id": {
+ "description": "The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself",
"type": "string",
"example": "bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"
},
"timezone": {
+ "description": "The timezone of the account",
"type": "string",
"example": ""
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "space"
},
"widgets_id": {
+ "description": "The id of the widgets",
"type": "string",
"example": "bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"
},
"workspace_object_id": {
+ "description": "The id of the workspace object",
"type": "string",
"example": "bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"
}
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index cf8fe16d36..f5647435cd 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -941,6 +941,7 @@
"type": "object",
"properties": {
"challenge_id": {
+ "description": "The challenge id associated with the displayed code and needed to solve the challenge for token",
"type": "string",
"example": "67647f5ecda913e9a2e11b26"
}
@@ -950,10 +951,12 @@
"type": "object",
"properties": {
"app_key": {
+ "description": "The permanent app key",
"type": "string",
"example": "zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="
},
"session_token": {
+ "description": "The ephemeral session token",
"type": "string",
"example": "eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"
}
@@ -963,6 +966,7 @@
"type": "object",
"properties": {
"path": {
+ "description": "The path the object was exported to",
"type": "string",
"example": "/path/to/export"
}
@@ -972,6 +976,7 @@
"type": "object",
"properties": {
"align": {
+ "description": "The alignment of the block",
"type": "string",
"enum": [
"AlignLeft",
@@ -982,10 +987,12 @@
"example": "AlignLeft"
},
"background_color": {
+ "description": "The background color of the block",
"type": "string",
"example": "red"
},
"children_ids": {
+ "description": "The ids of the block's children",
"type": "array",
"items": {
"type": "string"
@@ -995,16 +1002,28 @@
]
},
"file": {
- "$ref": "#/definitions/object.File"
+ "description": "The file of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.File"
+ }
+ ]
},
"id": {
+ "description": "The id of the block",
"type": "string",
"example": "64394517de52ad5acb89c66c"
},
"text": {
- "$ref": "#/definitions/object.Text"
+ "description": "The text of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Text"
+ }
+ ]
},
"vertical_align": {
+ "description": "The vertical alignment of the block",
"type": "string",
"enum": [
"VerticalAlignTop",
@@ -1019,30 +1038,37 @@
"type": "object",
"properties": {
"body": {
+ "description": "The body of the object",
"type": "string",
- "example": "Object Body"
+ "example": "This is the body of the object. Markdown syntax is supported here."
},
"description": {
+ "description": "The description of the object",
"type": "string",
- "example": "Object Description"
+ "example": "This is a description of the object."
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"object_type_unique_key": {
+ "description": "The unique key of the object type",
"type": "string",
"example": "ot-page"
},
"source": {
+ "description": "The source url, only applicable for bookmarks",
"type": "string",
- "example": "https://source.com"
+ "example": "https://bookmark-source.com"
},
"template_id": {
+ "description": "The id of the template to use",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
}
@@ -1052,10 +1078,12 @@
"type": "object",
"properties": {
"details": {
+ "description": "The details",
"type": "object",
"additionalProperties": true
},
"id": {
+ "description": "The id of the detail",
"type": "string",
"enum": [
"last_modified_date",
@@ -1073,30 +1101,39 @@
"type": "object",
"properties": {
"added_at": {
+ "description": "The added at of the file",
"type": "integer"
},
"hash": {
+ "description": "The hash of the file",
"type": "string"
},
"mime": {
+ "description": "The mime of the file",
"type": "string"
},
"name": {
+ "description": "The name of the file",
"type": "string"
},
"size": {
+ "description": "The size of the file",
"type": "integer"
},
"state": {
+ "description": "The state of the file",
"type": "string"
},
"style": {
+ "description": "The style of the file",
"type": "string"
},
"target_object_id": {
+ "description": "The target object id of the file",
"type": "string"
},
"type": {
+ "description": "The type of the file",
"type": "string"
}
}
@@ -1105,46 +1142,56 @@
"type": "object",
"properties": {
"blocks": {
+ "description": "The blocks of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Block"
}
},
"details": {
+ "description": "The details of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Detail"
}
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the object",
"type": "string",
"example": "bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"
},
"layout": {
+ "description": "The layout of the object",
"type": "string",
"example": "basic"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"root_id": {
+ "description": "The id of the object's root",
"type": "string",
"example": "bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"
},
"snippet": {
+ "description": "The snippet of the object, especially important for notes as they don't have a name",
"type": "string",
"example": "The beginning of the object body..."
},
"space_id": {
+ "description": "The id of the space the object is in",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "Page"
}
@@ -1154,7 +1201,12 @@
"type": "object",
"properties": {
"object": {
- "$ref": "#/definitions/object.Object"
+ "description": "The object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Object"
+ }
+ ]
}
}
},
@@ -1162,18 +1214,22 @@
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the template",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the template",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
},
"name": {
+ "description": "The name of the template",
"type": "string",
- "example": "Template Name"
+ "example": "My template"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "template"
}
@@ -1183,7 +1239,12 @@
"type": "object",
"properties": {
"template": {
- "$ref": "#/definitions/object.Template"
+ "description": "The template",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Template"
+ }
+ ]
}
}
},
@@ -1191,18 +1252,22 @@
"type": "object",
"properties": {
"checked": {
+ "description": "Whether the text is checked",
"type": "boolean",
"example": true
},
"color": {
+ "description": "The color of the text",
"type": "string",
"example": "red"
},
"icon": {
+ "description": "The icon of the text",
"type": "string",
"example": "📄"
},
"style": {
+ "description": "The style of the text",
"type": "string",
"enum": [
"Paragraph",
@@ -1223,8 +1288,9 @@
"example": "Paragraph"
},
"text": {
+ "description": "The text",
"type": "string",
- "example": "Some text"
+ "example": "Some text..."
}
}
},
@@ -1232,26 +1298,32 @@
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the type",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the type",
"type": "string",
"example": "bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"
},
"name": {
+ "description": "The name of the type",
"type": "string",
"example": "Page"
},
"recommended_layout": {
+ "description": "The recommended layout of the type",
"type": "string",
"example": "todo"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "type"
},
"unique_key": {
+ "description": "The unique key of the type",
"type": "string",
"example": "ot-page"
}
@@ -1261,7 +1333,12 @@
"type": "object",
"properties": {
"type": {
- "$ref": "#/definitions/object.Type"
+ "description": "The type",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Type"
+ }
+ ]
}
}
},
@@ -1269,13 +1346,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Object"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1283,13 +1366,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Template"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1297,13 +1386,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Type"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1311,13 +1406,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Member"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1325,13 +1426,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Space"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1339,22 +1446,22 @@
"type": "object",
"properties": {
"has_more": {
- "description": "whether there are more items available",
+ "description": "Indicates if there are more items available beyond the current result set",
"type": "boolean",
"example": true
},
"limit": {
- "description": "the current limit",
+ "description": "The maximum number of items returned in the result set",
"type": "integer",
"example": 100
},
"offset": {
- "description": "the current offset",
+ "description": "The number of items skipped before starting to collect the result set",
"type": "integer",
"example": 0
},
"total": {
- "description": "the total number of items available on that endpoint",
+ "description": "The total number of items available for the endpoint",
"type": "integer",
"example": 1024
}
@@ -1364,16 +1471,30 @@
"type": "object",
"properties": {
"query": {
- "type": "string"
+ "description": "The search term to look for in object names and snippets",
+ "type": "string",
+ "example": "test"
},
"sort": {
- "$ref": "#/definitions/search.SortOptions"
+ "description": "The sorting criteria and direction for the search results",
+ "allOf": [
+ {
+ "$ref": "#/definitions/search.SortOptions"
+ }
+ ]
},
"types": {
+ "description": "The types of objects to search for, specified by unique key or ID",
"type": "array",
"items": {
"type": "string"
- }
+ },
+ "example": [
+ "ot-note",
+ "ot-page",
+ "ot-678043f0cda9133be777049f",
+ "bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"
+ ]
}
}
},
@@ -1381,6 +1502,7 @@
"type": "object",
"properties": {
"direction": {
+ "description": "The direction to sort the search results",
"type": "string",
"default": "desc",
"enum": [
@@ -1389,6 +1511,7 @@
]
},
"timestamp": {
+ "description": "The timestamp to sort the search results by",
"type": "string",
"default": "last_modified_date",
"enum": [
@@ -1403,6 +1526,7 @@
"type": "object",
"properties": {
"name": {
+ "description": "The name of the space",
"type": "string",
"example": "New Space"
}
@@ -1412,7 +1536,12 @@
"type": "object",
"properties": {
"space": {
- "$ref": "#/definitions/space.Space"
+ "description": "The created space",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Space"
+ }
+ ]
}
}
},
@@ -1420,26 +1549,32 @@
"type": "object",
"properties": {
"global_name": {
+ "description": "The global name of the member in the network",
"type": "string",
"example": "john.any"
},
"icon": {
+ "description": "The icon of the member",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"
},
"id": {
+ "description": "The profile object id of the member",
"type": "string",
"example": "_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"
},
"identity": {
+ "description": "The identity of the member in the network",
"type": "string",
"example": "AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"
},
"name": {
+ "description": "The name of the member",
"type": "string",
"example": "John Doe"
},
"role": {
+ "description": "The role of the member",
"type": "string",
"enum": [
"Reader",
@@ -1450,6 +1585,7 @@
"example": "Owner"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "member"
}
@@ -1459,78 +1595,97 @@
"type": "object",
"properties": {
"account_space_id": {
+ "description": "The id of the account space",
"type": "string",
"example": "bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"
},
"analytics_id": {
+ "description": "The analytics id of the account",
"type": "string",
"example": "624aecdd-4797-4611-9d61-a2ae5f53cf1c"
},
"archive_object_id": {
+ "description": "The id of the archive object",
"type": "string",
"example": "bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"
},
"device_id": {
+ "description": "The id of the device",
"type": "string",
"example": "12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"
},
"gateway_url": {
+ "description": "The gateway url to serve files and media",
"type": "string",
"example": "http://127.0.0.1:31006"
},
"home_object_id": {
+ "description": "The id of the home object",
"type": "string",
"example": "bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"
},
"icon": {
+ "description": "The icon of the space",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"
},
"id": {
+ "description": "The id of the space",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"local_storage_path": {
+ "description": "The local storage path of the account",
"type": "string",
"example": "/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"
},
"marketplace_workspace_id": {
+ "description": "The id of the marketplace workspace",
"type": "string",
"example": "_anytype_marketplace"
},
"name": {
+ "description": "The name of the space",
"type": "string",
- "example": "Space Name"
+ "example": "My Space"
},
"network_id": {
+ "description": "The network id of the space",
"type": "string",
"example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
},
"profile_object_id": {
+ "description": "The id of the profile object",
"type": "string",
"example": "bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"
},
"space_view_id": {
+ "description": "The id of the space view",
"type": "string",
"example": "bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"
},
"tech_space_id": {
+ "description": "The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself",
"type": "string",
"example": "bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"
},
"timezone": {
+ "description": "The timezone of the account",
"type": "string",
"example": ""
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "space"
},
"widgets_id": {
+ "description": "The id of the widgets",
"type": "string",
"example": "bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"
},
"workspace_object_id": {
+ "description": "The id of the workspace object",
"type": "string",
"example": "bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"
}
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 550a59d1c6..c9ba287575 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -3,27 +3,33 @@ definitions:
auth.DisplayCodeResponse:
properties:
challenge_id:
+ description: The challenge id associated with the displayed code and needed
+ to solve the challenge for token
example: 67647f5ecda913e9a2e11b26
type: string
type: object
auth.TokenResponse:
properties:
app_key:
+ description: The permanent app key
example: zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=
type: string
session_token:
+ description: The ephemeral session token
example: eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII
type: string
type: object
export.ObjectExportResponse:
properties:
path:
+ description: The path the object was exported to
example: /path/to/export
type: string
type: object
object.Block:
properties:
align:
+ description: The alignment of the block
enum:
- AlignLeft
- AlignCenter
@@ -32,22 +38,30 @@ definitions:
example: AlignLeft
type: string
background_color:
+ description: The background color of the block
example: red
type: string
children_ids:
+ description: The ids of the block's children
example:
- '[''6797ce8ecda913cde14b02dc'']'
items:
type: string
type: array
file:
- $ref: '#/definitions/object.File'
+ allOf:
+ - $ref: '#/definitions/object.File'
+ description: The file of the block, if applicable
id:
+ description: The id of the block
example: 64394517de52ad5acb89c66c
type: string
text:
- $ref: '#/definitions/object.Text'
+ allOf:
+ - $ref: '#/definitions/object.Text'
+ description: The text of the block, if applicable
vertical_align:
+ description: The vertical alignment of the block
enum:
- VerticalAlignTop
- VerticalAlignMiddle
@@ -58,24 +72,31 @@ definitions:
object.CreateObjectRequest:
properties:
body:
- example: Object Body
+ description: The body of the object
+ example: This is the body of the object. Markdown syntax is supported here.
type: string
description:
- example: Object Description
+ description: The description of the object
+ example: This is a description of the object.
type: string
icon:
+ description: The icon of the object
example: "\U0001F4C4"
type: string
name:
- example: Object Name
+ description: The name of the object
+ example: My object
type: string
object_type_unique_key:
+ description: The unique key of the object type
example: ot-page
type: string
source:
- example: https://source.com
+ description: The source url, only applicable for bookmarks
+ example: https://bookmark-source.com
type: string
template_id:
+ description: The id of the template to use
example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
type: string
type: object
@@ -83,8 +104,10 @@ definitions:
properties:
details:
additionalProperties: true
+ description: The details
type: object
id:
+ description: The id of the detail
enum:
- last_modified_date
- last_modified_by
@@ -98,96 +121,128 @@ definitions:
object.File:
properties:
added_at:
+ description: The added at of the file
type: integer
hash:
+ description: The hash of the file
type: string
mime:
+ description: The mime of the file
type: string
name:
+ description: The name of the file
type: string
size:
+ description: The size of the file
type: integer
state:
+ description: The state of the file
type: string
style:
+ description: The style of the file
type: string
target_object_id:
+ description: The target object id of the file
type: string
type:
+ description: The type of the file
type: string
type: object
object.Object:
properties:
blocks:
+ description: The blocks of the object
items:
$ref: '#/definitions/object.Block'
type: array
details:
+ description: The details of the object
items:
$ref: '#/definitions/object.Detail'
type: array
icon:
+ description: The icon of the object
example: "\U0001F4C4"
type: string
id:
+ description: The id of the object
example: bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ
type: string
layout:
+ description: The layout of the object
example: basic
type: string
name:
- example: Object Name
+ description: The name of the object
+ example: My object
type: string
root_id:
+ description: The id of the object's root
example: bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u
type: string
snippet:
+ description: The snippet of the object, especially important for notes as
+ they don't have a name
example: The beginning of the object body...
type: string
space_id:
+ description: The id of the space the object is in
example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
type: string
type:
+ description: The type of the object
example: Page
type: string
type: object
object.ObjectResponse:
properties:
object:
- $ref: '#/definitions/object.Object'
+ allOf:
+ - $ref: '#/definitions/object.Object'
+ description: The object
type: object
object.Template:
properties:
icon:
+ description: The icon of the template
example: "\U0001F4C4"
type: string
id:
+ description: The id of the template
example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
type: string
name:
- example: Template Name
+ description: The name of the template
+ example: My template
type: string
type:
+ description: The type of the object
example: template
type: string
type: object
object.TemplateResponse:
properties:
template:
- $ref: '#/definitions/object.Template'
+ allOf:
+ - $ref: '#/definitions/object.Template'
+ description: The template
type: object
object.Text:
properties:
checked:
+ description: Whether the text is checked
example: true
type: boolean
color:
+ description: The color of the text
example: red
type: string
icon:
+ description: The icon of the text
example: "\U0001F4C4"
type: string
style:
+ description: The style of the text
enum:
- Paragraph
- Header1
@@ -206,106 +261,143 @@ definitions:
example: Paragraph
type: string
text:
- example: Some text
+ description: The text
+ example: Some text...
type: string
type: object
object.Type:
properties:
icon:
+ description: The icon of the type
example: "\U0001F4C4"
type: string
id:
+ description: The id of the type
example: bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu
type: string
name:
+ description: The name of the type
example: Page
type: string
recommended_layout:
+ description: The recommended layout of the type
example: todo
type: string
type:
+ description: The type of the object
example: type
type: string
unique_key:
+ description: The unique key of the type
example: ot-page
type: string
type: object
object.TypeResponse:
properties:
type:
- $ref: '#/definitions/object.Type'
+ allOf:
+ - $ref: '#/definitions/object.Type'
+ description: The type
type: object
pagination.PaginatedResponse-object_Object:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/object.Object'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-object_Template:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/object.Template'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-object_Type:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/object.Type'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-space_Member:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/space.Member'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-space_Space:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/space.Space'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginationMeta:
properties:
has_more:
- description: whether there are more items available
+ description: Indicates if there are more items available beyond the current
+ result set
example: true
type: boolean
limit:
- description: the current limit
+ description: The maximum number of items returned in the result set
example: 100
type: integer
offset:
- description: the current offset
+ description: The number of items skipped before starting to collect the result
+ set
example: 0
type: integer
total:
- description: the total number of items available on that endpoint
+ description: The total number of items available for the endpoint
example: 1024
type: integer
type: object
search.SearchRequest:
properties:
query:
+ description: The search term to look for in object names and snippets
+ example: test
type: string
sort:
- $ref: '#/definitions/search.SortOptions'
+ allOf:
+ - $ref: '#/definitions/search.SortOptions'
+ description: The sorting criteria and direction for the search results
types:
+ description: The types of objects to search for, specified by unique key or
+ ID
+ example:
+ - ot-note
+ - ot-page
+ - ot-678043f0cda9133be777049f
+ - bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q
items:
type: string
type: array
@@ -314,12 +406,14 @@ definitions:
properties:
direction:
default: desc
+ description: The direction to sort the search results
enum:
- asc
- desc
type: string
timestamp:
default: last_modified_date
+ description: The timestamp to sort the search results by
enum:
- created_date
- last_modified_date
@@ -329,32 +423,41 @@ definitions:
space.CreateSpaceRequest:
properties:
name:
+ description: The name of the space
example: New Space
type: string
type: object
space.CreateSpaceResponse:
properties:
space:
- $ref: '#/definitions/space.Space'
+ allOf:
+ - $ref: '#/definitions/space.Space'
+ description: The created space
type: object
space.Member:
properties:
global_name:
+ description: The global name of the member in the network
example: john.any
type: string
icon:
+ description: The icon of the member
example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100
type: string
id:
+ description: The profile object id of the member
example: _participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ
type: string
identity:
+ description: The identity of the member in the network
example: AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ
type: string
name:
+ description: The name of the member
example: John Doe
type: string
role:
+ description: The role of the member
enum:
- Reader
- Writer
@@ -363,66 +466,87 @@ definitions:
example: Owner
type: string
type:
+ description: The type of the object
example: member
type: string
type: object
space.Space:
properties:
account_space_id:
+ description: The id of the account space
example: bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1
type: string
analytics_id:
+ description: The analytics id of the account
example: 624aecdd-4797-4611-9d61-a2ae5f53cf1c
type: string
archive_object_id:
+ description: The id of the archive object
example: bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri
type: string
device_id:
+ description: The id of the device
example: 12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF
type: string
gateway_url:
+ description: The gateway url to serve files and media
example: http://127.0.0.1:31006
type: string
home_object_id:
+ description: The id of the home object
example: bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya
type: string
icon:
+ description: The icon of the space
example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay
type: string
id:
+ description: The id of the space
example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
type: string
local_storage_path:
+ description: The local storage path of the account
example: /Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha
type: string
marketplace_workspace_id:
+ description: The id of the marketplace workspace
example: _anytype_marketplace
type: string
name:
- example: Space Name
+ description: The name of the space
+ example: My Space
type: string
network_id:
+ description: The network id of the space
example: N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU
type: string
profile_object_id:
+ description: The id of the profile object
example: bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4
type: string
space_view_id:
+ description: The id of the space view
example: bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy
type: string
tech_space_id:
+ description: The id of tech space, where objects outside of user's actual
+ spaces are stored, e.g. spaces itself
example: bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1
type: string
timezone:
+ description: The timezone of the account
example: ""
type: string
type:
+ description: The type of the object
example: space
type: string
widgets_id:
+ description: The id of the widgets
example: bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva
type: string
workspace_object_id:
+ description: The id of the workspace object
example: bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y
type: string
type: object
diff --git a/core/api/internal/auth/model.go b/core/api/internal/auth/model.go
index 2d34926f56..221797cd36 100644
--- a/core/api/internal/auth/model.go
+++ b/core/api/internal/auth/model.go
@@ -1,10 +1,10 @@
package auth
type DisplayCodeResponse struct {
- ChallengeId string `json:"challenge_id" example:"67647f5ecda913e9a2e11b26"`
+ ChallengeId string `json:"challenge_id" example:"67647f5ecda913e9a2e11b26"` // The challenge id associated with the displayed code and needed to solve the challenge for token
}
type TokenResponse struct {
- SessionToken string `json:"session_token" example:"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"`
- AppKey string `json:"app_key" example:"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="`
+ SessionToken string `json:"session_token" example:"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"` // The ephemeral session token
+ AppKey string `json:"app_key" example:"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="` // The permanent app key
}
diff --git a/core/api/internal/export/model.go b/core/api/internal/export/model.go
index dde2422462..e6541b62bc 100644
--- a/core/api/internal/export/model.go
+++ b/core/api/internal/export/model.go
@@ -1,9 +1,9 @@
package export
type ObjectExportRequest struct {
- Path string `json:"path" example:"/path/to/export"`
+ Path string `json:"path" example:"/path/to/export"` // The path to export the object to
}
type ObjectExportResponse struct {
- Path string `json:"path" example:"/path/to/export"`
+ Path string `json:"path" example:"/path/to/export"` // The path the object was exported to
}
diff --git a/core/api/internal/object/model.go b/core/api/internal/object/model.go
index 70ba449aa0..d591214913 100644
--- a/core/api/internal/object/model.go
+++ b/core/api/internal/object/model.go
@@ -1,93 +1,93 @@
package object
type CreateObjectRequest struct {
- Name string `json:"name" example:"Object Name"`
- Icon string `json:"icon" example:"📄"`
- Description string `json:"description" example:"Object Description"`
- Body string `json:"body" example:"Object Body"`
- Source string `json:"source" example:"https://source.com"`
- TemplateId string `json:"template_id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"`
- ObjectTypeUniqueKey string `json:"object_type_unique_key" example:"ot-page"`
+ Name string `json:"name" example:"My object"` // The name of the object
+ Icon string `json:"icon" example:"📄"` // The icon of the object
+ Description string `json:"description" example:"This is a description of the object."` // The description of the object
+ Body string `json:"body" example:"This is the body of the object. Markdown syntax is supported here."` // The body of the object
+ Source string `json:"source" example:"https://bookmark-source.com"` // The source url, only applicable for bookmarks
+ TemplateId string `json:"template_id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"` // The id of the template to use
+ ObjectTypeUniqueKey string `json:"object_type_unique_key" example:"ot-page"` // The unique key of the object type
}
type ObjectResponse struct {
- Object Object `json:"object"`
+ Object Object `json:"object"` // The object
}
type Object struct {
- Type string `json:"type" example:"Page"`
- Id string `json:"id" example:"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"`
- Name string `json:"name" example:"Object Name"`
- Icon string `json:"icon" example:"📄"`
- Snippet string `json:"snippet" example:"The beginning of the object body..."`
- Layout string `json:"layout" example:"basic"`
- SpaceId string `json:"space_id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"`
- RootId string `json:"root_id" example:"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"`
- Blocks []Block `json:"blocks"`
- Details []Detail `json:"details"`
+ Type string `json:"type" example:"Page"` // The type of the object
+ Id string `json:"id" example:"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"` // The id of the object
+ Name string `json:"name" example:"My object"` // The name of the object
+ Icon string `json:"icon" example:"📄"` // The icon of the object
+ Snippet string `json:"snippet" example:"The beginning of the object body..."` // The snippet of the object, especially important for notes as they don't have a name
+ Layout string `json:"layout" example:"basic"` // The layout of the object
+ SpaceId string `json:"space_id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"` // The id of the space the object is in
+ RootId string `json:"root_id" example:"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"` // The id of the object's root
+ Blocks []Block `json:"blocks"` // The blocks of the object
+ Details []Detail `json:"details"` // The details of the object
}
type Block struct {
- Id string `json:"id" example:"64394517de52ad5acb89c66c"`
- ChildrenIds []string `json:"children_ids" example:"['6797ce8ecda913cde14b02dc']"`
- BackgroundColor string `json:"background_color" example:"red"`
- Align string `json:"align" enums:"AlignLeft,AlignCenter,AlignRight,AlignJustify" example:"AlignLeft"`
- VerticalAlign string `json:"vertical_align" enums:"VerticalAlignTop,VerticalAlignMiddle,VerticalAlignBottom" example:"VerticalAlignTop"`
- Text *Text `json:"text,omitempty"`
- File *File `json:"file,omitempty"`
+ Id string `json:"id" example:"64394517de52ad5acb89c66c"` // The id of the block
+ ChildrenIds []string `json:"children_ids" example:"['6797ce8ecda913cde14b02dc']"` // The ids of the block's children
+ BackgroundColor string `json:"background_color" example:"red"` // The background color of the block
+ Align string `json:"align" enums:"AlignLeft,AlignCenter,AlignRight,AlignJustify" example:"AlignLeft"` // The alignment of the block
+ VerticalAlign string `json:"vertical_align" enums:"VerticalAlignTop,VerticalAlignMiddle,VerticalAlignBottom" example:"VerticalAlignTop"` // The vertical alignment of the block
+ Text *Text `json:"text,omitempty"` // The text of the block, if applicable
+ File *File `json:"file,omitempty"` // The file of the block, if applicable
}
type Text struct {
- Text string `json:"text" example:"Some text"`
- Style string `json:"style" enums:"Paragraph,Header1,Header2,Header3,Header4,Quote,Code,Title,Checkbox,Marked,Numbered,Toggle,Description,Callout" example:"Paragraph"`
- Checked bool `json:"checked" example:"true"`
- Color string `json:"color" example:"red"`
- Icon string `json:"icon" example:"📄"`
+ Text string `json:"text" example:"Some text..."` // The text
+ Style string `json:"style" enums:"Paragraph,Header1,Header2,Header3,Header4,Quote,Code,Title,Checkbox,Marked,Numbered,Toggle,Description,Callout" example:"Paragraph"` // The style of the text
+ Checked bool `json:"checked" example:"true"` // Whether the text is checked
+ Color string `json:"color" example:"red"` // The color of the text
+ Icon string `json:"icon" example:"📄"` // The icon of the text
}
type File struct {
- Hash string `json:"hash"`
- Name string `json:"name"`
- Type string `json:"type"`
- Mime string `json:"mime"`
- Size int `json:"size"`
- AddedAt int `json:"added_at"`
- TargetObjectId string `json:"target_object_id"`
- State string `json:"state"`
- Style string `json:"style"`
+ Hash string `json:"hash"` // The hash of the file
+ Name string `json:"name"` // The name of the file
+ Type string `json:"type"` // The type of the file
+ Mime string `json:"mime"` // The mime of the file
+ Size int `json:"size"` // The size of the file
+ AddedAt int `json:"added_at"` // The added at of the file
+ TargetObjectId string `json:"target_object_id"` // The target object id of the file
+ State string `json:"state"` // The state of the file
+ Style string `json:"style"` // The style of the file
}
type Detail struct {
- Id string `json:"id" enums:"last_modified_date,last_modified_by,created_date,created_by,last_opened_date,tags" example:"last_modified_date"`
- Details map[string]interface{} `json:"details"`
+ Id string `json:"id" enums:"last_modified_date,last_modified_by,created_date,created_by,last_opened_date,tags" example:"last_modified_date"` // The id of the detail
+ Details map[string]interface{} `json:"details"` // The details
}
type Tag struct {
- Id string `json:"id" example:"bafyreiaixlnaefu3ci22zdenjhsdlyaeeoyjrsid5qhfeejzlccijbj7sq"`
- Name string `json:"name" example:"Tag Name"`
- Color string `json:"color" example:"yellow"`
+ Id string `json:"id" example:"bafyreiaixlnaefu3ci22zdenjhsdlyaeeoyjrsid5qhfeejzlccijbj7sq"` // The id of the tag
+ Name string `json:"name" example:"in-progress"` // The name of the tag
+ Color string `json:"color" example:"yellow"` // The color of the tag
}
type TypeResponse struct {
- Type Type `json:"type"`
+ Type Type `json:"type"` // The type
}
type Type struct {
- Type string `json:"type" example:"type"`
- Id string `json:"id" example:"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"`
- UniqueKey string `json:"unique_key" example:"ot-page"`
- Name string `json:"name" example:"Page"`
- Icon string `json:"icon" example:"📄"`
- RecommendedLayout string `json:"recommended_layout" example:"todo"`
+ Type string `json:"type" example:"type"` // The type of the object
+ Id string `json:"id" example:"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"` // The id of the type
+ UniqueKey string `json:"unique_key" example:"ot-page"` // The unique key of the type
+ Name string `json:"name" example:"Page"` // The name of the type
+ Icon string `json:"icon" example:"📄"` // The icon of the type
+ RecommendedLayout string `json:"recommended_layout" example:"todo"` // The recommended layout of the type
}
type TemplateResponse struct {
- Template Template `json:"template"`
+ Template Template `json:"template"` // The template
}
type Template struct {
- Type string `json:"type" example:"template"`
- Id string `json:"id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"`
- Name string `json:"name" example:"Template Name"`
- Icon string `json:"icon" example:"📄"`
+ Type string `json:"type" example:"template"` // The type of the object
+ Id string `json:"id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"` // The id of the template
+ Name string `json:"name" example:"My template"` // The name of the template
+ Icon string `json:"icon" example:"📄"` // The icon of the template
}
diff --git a/core/api/internal/object/service_test.go b/core/api/internal/object/service_test.go
index 10ba7e1c4d..5ae1f6ba25 100644
--- a/core/api/internal/object/service_test.go
+++ b/core/api/internal/object/service_test.go
@@ -390,7 +390,7 @@ func TestObjectService_CreateObject(t *testing.T) {
bundle.RelationKeyOrigin.String(): pbtypes.Int64(int64(model.ObjectOrigin_api)),
},
},
- TemplateId: "",
+ TemplateId: mockedTemplateId,
SpaceId: mockedSpaceId,
ObjectTypeUniqueKey: mockedObjectTypeUniqueKey,
WithChat: false,
@@ -483,10 +483,9 @@ func TestObjectService_CreateObject(t *testing.T) {
// when
object, err := fx.CreateObject(ctx, mockedSpaceId, CreateObjectRequest{
- Name: mockedObjectName,
- Icon: mockedObjectIcon,
- // TODO: use actual values
- TemplateId: "",
+ Name: mockedObjectName,
+ Icon: mockedObjectIcon,
+ TemplateId: mockedTemplateId,
ObjectTypeUniqueKey: mockedObjectTypeUniqueKey,
})
diff --git a/core/api/internal/search/model.go b/core/api/internal/search/model.go
index f52cf59e42..1709338418 100644
--- a/core/api/internal/search/model.go
+++ b/core/api/internal/search/model.go
@@ -1,12 +1,12 @@
package search
type SearchRequest struct {
- Query string `json:"query"`
- Types []string `json:"types"`
- Sort SortOptions `json:"sort"`
+ Query string `json:"query" example:"test"` // The search term to look for in object names and snippets
+ Types []string `json:"types" example:"ot-note,ot-page,ot-678043f0cda9133be777049f,bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"` // The types of objects to search for, specified by unique key or ID
+ Sort SortOptions `json:"sort"` // The sorting criteria and direction for the search results
}
type SortOptions struct {
- Direction string `json:"direction" enums:"asc,desc" default:"desc"`
- Timestamp string `json:"timestamp" enums:"created_date,last_modified_date,last_opened_date" default:"last_modified_date"`
+ Direction string `json:"direction" enums:"asc,desc" default:"desc"` // The direction to sort the search results
+ Timestamp string `json:"timestamp" enums:"created_date,last_modified_date,last_opened_date" default:"last_modified_date"` // The timestamp to sort the search results by
}
diff --git a/core/api/internal/space/model.go b/core/api/internal/space/model.go
index d13951c3f5..73cbe732be 100644
--- a/core/api/internal/space/model.go
+++ b/core/api/internal/space/model.go
@@ -1,41 +1,41 @@
package space
type CreateSpaceRequest struct {
- Name string `json:"name" example:"New Space"`
+ Name string `json:"name" example:"New Space"` // The name of the space
}
type CreateSpaceResponse struct {
- Space Space `json:"space"`
+ Space Space `json:"space"` // The created space
}
type Space struct {
- Type string `json:"type" example:"space"`
- Id string `json:"id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"`
- Name string `json:"name" example:"Space Name"`
- Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"`
- HomeObjectId string `json:"home_object_id" example:"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"`
- ArchiveObjectId string `json:"archive_object_id" example:"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"`
- ProfileObjectId string `json:"profile_object_id" example:"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"`
- MarketplaceWorkspaceId string `json:"marketplace_workspace_id" example:"_anytype_marketplace"`
- WorkspaceObjectId string `json:"workspace_object_id" example:"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"`
- DeviceId string `json:"device_id" example:"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"`
- AccountSpaceId string `json:"account_space_id" example:"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"`
- WidgetsId string `json:"widgets_id" example:"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"`
- SpaceViewId string `json:"space_view_id" example:"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"`
- TechSpaceId string `json:"tech_space_id" example:"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"`
- GatewayUrl string `json:"gateway_url" example:"http://127.0.0.1:31006"`
- LocalStoragePath string `json:"local_storage_path" example:"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"`
- Timezone string `json:"timezone" example:""`
- AnalyticsId string `json:"analytics_id" example:"624aecdd-4797-4611-9d61-a2ae5f53cf1c"`
- NetworkId string `json:"network_id" example:"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"`
+ Type string `json:"type" example:"space"` // The type of the object
+ Id string `json:"id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"` // The id of the space
+ Name string `json:"name" example:"My Space"` // The name of the space
+ Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"` // The icon of the space
+ HomeObjectId string `json:"home_object_id" example:"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"` // The id of the home object
+ ArchiveObjectId string `json:"archive_object_id" example:"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"` // The id of the archive object
+ ProfileObjectId string `json:"profile_object_id" example:"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"` // The id of the profile object
+ MarketplaceWorkspaceId string `json:"marketplace_workspace_id" example:"_anytype_marketplace"` // The id of the marketplace workspace
+ WorkspaceObjectId string `json:"workspace_object_id" example:"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"` // The id of the workspace object
+ DeviceId string `json:"device_id" example:"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"` // The id of the device
+ AccountSpaceId string `json:"account_space_id" example:"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"` // The id of the account space
+ WidgetsId string `json:"widgets_id" example:"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"` // The id of the widgets
+ SpaceViewId string `json:"space_view_id" example:"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"` // The id of the space view
+ TechSpaceId string `json:"tech_space_id" example:"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"` // The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself
+ GatewayUrl string `json:"gateway_url" example:"http://127.0.0.1:31006"` // The gateway url to serve files and media
+ LocalStoragePath string `json:"local_storage_path" example:"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"` // The local storage path of the account
+ Timezone string `json:"timezone" example:""` // The timezone of the account
+ AnalyticsId string `json:"analytics_id" example:"624aecdd-4797-4611-9d61-a2ae5f53cf1c"` // The analytics id of the account
+ NetworkId string `json:"network_id" example:"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"` // The network id of the space
}
type Member struct {
- Type string `json:"type" example:"member"`
- Id string `json:"id" example:"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"`
- Name string `json:"name" example:"John Doe"`
- Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"`
- Identity string `json:"identity" example:"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"`
- GlobalName string `json:"global_name" example:"john.any"`
- Role string `json:"role" enums:"Reader,Writer,Owner,NoPermission" example:"Owner"`
+ Type string `json:"type" example:"member"` // The type of the object
+ Id string `json:"id" example:"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"` // The profile object id of the member
+ Name string `json:"name" example:"John Doe"` // The name of the member
+ Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"` // The icon of the member
+ Identity string `json:"identity" example:"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"` // The identity of the member in the network
+ GlobalName string `json:"global_name" example:"john.any"` // The global name of the member in the network
+ Role string `json:"role" enums:"Reader,Writer,Owner,NoPermission" example:"Owner"` // The role of the member
}
diff --git a/core/api/pagination/model.go b/core/api/pagination/model.go
index 06539ce635..3d679fec48 100644
--- a/core/api/pagination/model.go
+++ b/core/api/pagination/model.go
@@ -1,13 +1,13 @@
package pagination
type PaginationMeta struct {
- Total int `json:"total" example:"1024"` // the total number of items available on that endpoint
- Offset int `json:"offset" example:"0"` // the current offset
- Limit int `json:"limit" example:"100"` // the current limit
- HasMore bool `json:"has_more" example:"true"` // whether there are more items available
+ Total int `json:"total" example:"1024"` // The total number of items available for the endpoint
+ Offset int `json:"offset" example:"0"` // The number of items skipped before starting to collect the result set
+ Limit int `json:"limit" example:"100"` // The maximum number of items returned in the result set
+ HasMore bool `json:"has_more" example:"true"` // Indicates if there are more items available beyond the current result set
}
type PaginatedResponse[T any] struct {
- Data []T `json:"data"`
- Pagination PaginationMeta `json:"pagination"`
+ Data []T `json:"data"` // The list of items in the current result set
+ Pagination PaginationMeta `json:"pagination"` // The pagination metadata for the response
}
From c7acd87e2b90c48e49caa24ee2fdee1104367a30 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Wed, 29 Jan 2025 15:08:08 +0100
Subject: [PATCH 02/31] GO-4459: Add swagger examples for errors
---
core/api/docs/docs.go | 15 ++++++++-----
core/api/docs/swagger.json | 15 ++++++++-----
core/api/docs/swagger.yaml | 5 +++++
core/api/util/error.go | 46 +++++++++++++++++++++++---------------
4 files changed, 53 insertions(+), 28 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 34e2a56f64..239cbb9d84 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -1704,7 +1704,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Forbidden"
}
}
}
@@ -1717,7 +1718,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Resource not found"
}
}
}
@@ -1730,7 +1732,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Internal server error"
}
}
}
@@ -1743,7 +1746,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Unauthorized"
}
}
}
@@ -1756,7 +1760,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Bad request"
}
}
}
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index f5647435cd..72c7919b2c 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -1698,7 +1698,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Forbidden"
}
}
}
@@ -1711,7 +1712,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Resource not found"
}
}
}
@@ -1724,7 +1726,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Internal server error"
}
}
}
@@ -1737,7 +1740,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Unauthorized"
}
}
}
@@ -1750,7 +1754,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Bad request"
}
}
}
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index c9ba287575..fbbc53a88e 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -555,6 +555,7 @@ definitions:
error:
properties:
message:
+ example: Forbidden
type: string
type: object
type: object
@@ -563,6 +564,7 @@ definitions:
error:
properties:
message:
+ example: Resource not found
type: string
type: object
type: object
@@ -571,6 +573,7 @@ definitions:
error:
properties:
message:
+ example: Internal server error
type: string
type: object
type: object
@@ -579,6 +582,7 @@ definitions:
error:
properties:
message:
+ example: Unauthorized
type: string
type: object
type: object
@@ -587,6 +591,7 @@ definitions:
error:
properties:
message:
+ example: Bad request
type: string
type: object
type: object
diff --git a/core/api/util/error.go b/core/api/util/error.go
index b7553f3fd2..acec46041c 100644
--- a/core/api/util/error.go
+++ b/core/api/util/error.go
@@ -5,38 +5,38 @@ import (
"net/http"
)
-// 400
+// ValidationError is a struct for 400 errors
type ValidationError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Bad request"`
} `json:"error"`
}
-// 401
+// UnauthorizedError is a struct for 401 errors
type UnauthorizedError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Unauthorized"`
} `json:"error"`
}
-// 403
+// ForbiddenError is a struct for 403 errors
type ForbiddenError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Forbidden"`
} `json:"error"`
}
-// 404
+// NotFoundError is a struct for 404 errors
type NotFoundError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Resource not found"`
} `json:"error"`
}
-// 500
+// ServerError is a struct for 500 errors
type ServerError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Internal server error"`
} `json:"error"`
}
@@ -72,10 +72,11 @@ func MapErrorCode(err error, mappings ...errCodeMapping) int {
// for the given HTTP code, embedding the supplied message.
func CodeToAPIError(code int, message string) any {
switch code {
- case http.StatusNotFound:
- return NotFoundError{
+
+ case http.StatusBadRequest:
+ return ValidationError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Bad request"`
}{
Message: message,
},
@@ -84,16 +85,25 @@ func CodeToAPIError(code int, message string) any {
case http.StatusUnauthorized:
return UnauthorizedError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Unauthorized"`
}{
Message: message,
},
}
- case http.StatusBadRequest:
- return ValidationError{
+ case http.StatusForbidden:
+ return ForbiddenError{
+ Error: struct {
+ Message string `json:"message" example:"Forbidden"`
+ }{
+ Message: message,
+ },
+ }
+
+ case http.StatusNotFound:
+ return NotFoundError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Resource not found"`
}{
Message: message,
},
@@ -102,7 +112,7 @@ func CodeToAPIError(code int, message string) any {
default:
return ServerError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Internal server error"`
}{
Message: message,
},
From cfbe6135e17b86c347649809b3d7508f10822ab5 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 31 Jan 2025 10:50:54 +0100
Subject: [PATCH 03/31] GO-4459: Return proper api errors and 423 from
middleware
---
core/api/docs/docs.go | 32 +++++++++++++++++++++++++++++
core/api/docs/swagger.json | 32 +++++++++++++++++++++++++++++
core/api/docs/swagger.yaml | 21 +++++++++++++++++++
core/api/internal/object/handler.go | 2 ++
core/api/internal/space/handler.go | 1 +
core/api/server/middleware.go | 16 ++++++++++-----
core/api/util/error.go | 16 +++++++++++++++
7 files changed, 115 insertions(+), 5 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 239cbb9d84..66823dff8e 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -268,6 +268,12 @@ const docTemplate = `{
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -440,6 +446,12 @@ const docTemplate = `{
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -556,6 +568,12 @@ const docTemplate = `{
"$ref": "#/definitions/util.NotFoundError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -1725,6 +1743,20 @@ const docTemplate = `{
}
}
},
+ "util.RateLimitError": {
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "example": "Rate limit exceeded"
+ }
+ }
+ }
+ }
+ },
"util.ServerError": {
"type": "object",
"properties": {
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index 72c7919b2c..13034aae6a 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -262,6 +262,12 @@
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -434,6 +440,12 @@
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -550,6 +562,12 @@
"$ref": "#/definitions/util.NotFoundError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -1719,6 +1737,20 @@
}
}
},
+ "util.RateLimitError": {
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "example": "Rate limit exceeded"
+ }
+ }
+ }
+ }
+ },
"util.ServerError": {
"type": "object",
"properties": {
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index fbbc53a88e..29f3e2d8f2 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -568,6 +568,15 @@ definitions:
type: string
type: object
type: object
+ util.RateLimitError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Rate limit exceeded
+ type: string
+ type: object
+ type: object
util.ServerError:
properties:
error:
@@ -775,6 +784,10 @@ paths:
description: Unauthorized
schema:
$ref: '#/definitions/util.UnauthorizedError'
+ "423":
+ description: Rate limit exceeded
+ schema:
+ $ref: '#/definitions/util.RateLimitError'
"500":
description: Internal server error
schema:
@@ -892,6 +905,10 @@ paths:
description: Unauthorized
schema:
$ref: '#/definitions/util.UnauthorizedError'
+ "423":
+ description: Rate limit exceeded
+ schema:
+ $ref: '#/definitions/util.RateLimitError'
"500":
description: Internal server error
schema:
@@ -933,6 +950,10 @@ paths:
description: Resource not found
schema:
$ref: '#/definitions/util.NotFoundError'
+ "423":
+ description: Rate limit exceeded
+ schema:
+ $ref: '#/definitions/util.RateLimitError'
"500":
description: Internal server error
schema:
diff --git a/core/api/internal/object/handler.go b/core/api/internal/object/handler.go
index 671f255839..57c1e2e877 100644
--- a/core/api/internal/object/handler.go
+++ b/core/api/internal/object/handler.go
@@ -91,6 +91,7 @@ func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 403 {object} util.ForbiddenError "Forbidden"
// @Failure 404 {object} util.NotFoundError "Resource not found"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
// @Router /spaces/{space_id}/objects/{object_id} [delete]
func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
@@ -126,6 +127,7 @@ func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Success 200 {object} ObjectResponse "The created object"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
// @Router /spaces/{space_id}/objects [post]
func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
diff --git a/core/api/internal/space/handler.go b/core/api/internal/space/handler.go
index 2a6ca043de..962423a3e0 100644
--- a/core/api/internal/space/handler.go
+++ b/core/api/internal/space/handler.go
@@ -52,6 +52,7 @@ func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
// @Success 200 {object} CreateSpaceResponse "Space created successfully"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
// @Router /spaces [post]
func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
diff --git a/core/api/server/middleware.go b/core/api/server/middleware.go
index da05740b8c..d2a2d23c94 100644
--- a/core/api/server/middleware.go
+++ b/core/api/server/middleware.go
@@ -11,6 +11,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/anyproto/anytype-heart/core/anytype/account"
+ "github.com/anyproto/anytype-heart/core/api/util"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb/service"
)
@@ -26,7 +27,8 @@ func (s *Server) rateLimit(max float64) gin.HandlerFunc {
return func(c *gin.Context) {
httpError := tollbooth.LimitByRequest(lmt, c.Writer, c.Request)
if httpError != nil {
- c.AbortWithStatusJSON(httpError.StatusCode, gin.H{"error": httpError.Message})
+ apiErr := util.CodeToAPIError(httpError.StatusCode, httpError.Message)
+ c.AbortWithStatusJSON(httpError.StatusCode, apiErr)
return
}
c.Next()
@@ -38,12 +40,14 @@ func (s *Server) ensureAuthenticated(mw service.ClientCommandsServer) gin.Handle
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
- c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing Authorization header"})
+ apiErr := util.CodeToAPIError(http.StatusUnauthorized, "Missing Authorization header")
+ c.AbortWithStatusJSON(http.StatusUnauthorized, apiErr)
return
}
if !strings.HasPrefix(authHeader, "Bearer ") {
- c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid Authorization header format"})
+ apiErr := util.CodeToAPIError(http.StatusUnauthorized, "Invalid Authorization header format")
+ c.AbortWithStatusJSON(http.StatusUnauthorized, apiErr)
return
}
key := strings.TrimPrefix(authHeader, "Bearer ")
@@ -57,7 +61,8 @@ func (s *Server) ensureAuthenticated(mw service.ClientCommandsServer) gin.Handle
if !exists {
response := mw.WalletCreateSession(context.Background(), &pb.RpcWalletCreateSessionRequest{Auth: &pb.RpcWalletCreateSessionRequestAuthOfAppKey{AppKey: key}})
if response.Error.Code != pb.RpcWalletCreateSessionResponseError_NULL {
- c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
+ apiErr := util.CodeToAPIError(http.StatusUnauthorized, "Invalid token")
+ c.AbortWithStatusJSON(http.StatusUnauthorized, apiErr)
return
}
token = response.Token
@@ -78,7 +83,8 @@ func (s *Server) ensureAccountInfo(accountService account.Service) gin.HandlerFu
return func(c *gin.Context) {
accInfo, err := accountService.GetInfo(context.Background())
if err != nil {
- c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to get account info: %v", err)})
+ apiErr := util.CodeToAPIError(http.StatusInternalServerError, fmt.Sprintf("failed to get account info: %v", err))
+ c.AbortWithStatusJSON(http.StatusInternalServerError, apiErr)
return
}
diff --git a/core/api/util/error.go b/core/api/util/error.go
index acec46041c..77aeff751e 100644
--- a/core/api/util/error.go
+++ b/core/api/util/error.go
@@ -33,6 +33,13 @@ type NotFoundError struct {
} `json:"error"`
}
+// RateLimitError is a struct for 423 errors
+type RateLimitError struct {
+ Error struct {
+ Message string `json:"message" example:"Rate limit exceeded"`
+ } `json:"error"`
+}
+
// ServerError is a struct for 500 errors
type ServerError struct {
Error struct {
@@ -109,6 +116,15 @@ func CodeToAPIError(code int, message string) any {
},
}
+ case http.StatusTooManyRequests:
+ return RateLimitError{
+ Error: struct {
+ Message string `json:"message" example:"Rate limit exceeded"`
+ }{
+ Message: message,
+ },
+ }
+
default:
return ServerError{
Error: struct {
From 86975463fdc2f5909f458b1c6f33a76c989b68d6 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Mon, 3 Feb 2025 16:24:56 +0100
Subject: [PATCH 04/31] GO-4459: Add last_modified sort criterion as fallback
for last_opened sort
---
core/api/internal/search/service.go | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/core/api/internal/search/service.go b/core/api/internal/search/service.go
index 58c783ef38..ecd2408718 100644
--- a/core/api/internal/search/service.go
+++ b/core/api/internal/search/service.go
@@ -48,7 +48,7 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
baseFilters := s.prepareBaseFilters()
queryFilters := s.prepareQueryFilter(request.Query)
sorts := s.prepareSorts(request.Sort)
- dateToSortAfter := sorts.RelationKey
+ dateToSortAfter := sorts[0].RelationKey
allResponses := make([]*pb.RpcObjectSearchResponse, 0, len(spaces))
for _, space := range spaces {
@@ -59,7 +59,7 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
objResp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
SpaceId: space.Id,
Filters: filters,
- Sorts: []*model.BlockContentDataviewSort{sorts},
+ Sorts: sorts,
Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeySpaceId.String(), dateToSortAfter},
Limit: int32(offset + limit), // nolint: gosec
})
@@ -91,7 +91,7 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
}
// sort after posix last_modified_date to achieve descending sort order across all spaces
- sort.Slice(combinedRecords, func(i, j int) bool {
+ sort.SliceStable(combinedRecords, func(i, j int) bool {
return combinedRecords[i].DateToSortAfter > combinedRecords[j].DateToSortAfter
})
@@ -118,12 +118,12 @@ func (s *SearchService) Search(ctx context.Context, spaceId string, request Sear
filters := s.combineFilters(model.BlockContentDataviewFilter_And, baseFilters, queryFilters, typeFilters)
sorts := s.prepareSorts(request.Sort)
- dateToSortAfter := sorts.RelationKey
+ dateToSortAfter := sorts[0].RelationKey
resp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
SpaceId: spaceId,
Filters: filters,
- Sorts: []*model.BlockContentDataviewSort{sorts},
+ Sorts: sorts,
Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeySpaceId.String(), dateToSortAfter},
})
@@ -262,14 +262,28 @@ func (s *SearchService) prepareObjectTypeFilters(spaceId string, objectTypes []s
}
// prepareSorts returns a sort filter based on the given sort parameters
-func (s *SearchService) prepareSorts(sort SortOptions) *model.BlockContentDataviewSort {
- return &model.BlockContentDataviewSort{
+func (s *SearchService) prepareSorts(sort SortOptions) []*model.BlockContentDataviewSort {
+ primarySort := &model.BlockContentDataviewSort{
RelationKey: s.getSortRelationKey(sort.Timestamp),
Type: s.getSortDirection(sort.Direction),
Format: model.RelationFormat_date,
IncludeTime: true,
EmptyPlacement: model.BlockContentDataviewSort_NotSpecified,
}
+
+ // last_opened_date possibly is empty, wherefore we sort by last_modified_date as secondary criterion
+ if primarySort.RelationKey == bundle.RelationKeyLastOpenedDate.String() {
+ secondarySort := &model.BlockContentDataviewSort{
+ RelationKey: bundle.RelationKeyLastModifiedDate.String(),
+ Type: s.getSortDirection(sort.Direction),
+ Format: model.RelationFormat_date,
+ IncludeTime: true,
+ EmptyPlacement: model.BlockContentDataviewSort_NotSpecified,
+ }
+ return []*model.BlockContentDataviewSort{primarySort, secondarySort}
+ }
+
+ return []*model.BlockContentDataviewSort{primarySort}
}
// getSortRelationKey returns the relation key for the given sort timestamp
From 6f238c480fb3b8556022275a44044d831d2904e0 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Mon, 3 Feb 2025 16:25:17 +0100
Subject: [PATCH 05/31] GO-4459: Add ANYTYPE_API_DEBUG to run config
---
.run/Run.run.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.run/Run.run.xml b/.run/Run.run.xml
index 47b924fe55..78502fd86d 100644
--- a/.run/Run.run.xml
+++ b/.run/Run.run.xml
@@ -9,6 +9,7 @@
+
From e4fa847daee41b06d9101d5fcbbeeeef9102ef51 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 9 Feb 2025 18:32:21 +0100
Subject: [PATCH 06/31] GO-4459: Add endpoint for single space
---
core/api/docs/docs.go | 77 ++++++++++++++++++++++++------
core/api/docs/swagger.json | 77 ++++++++++++++++++++++++------
core/api/docs/swagger.yaml | 48 +++++++++++++++----
core/api/internal/space/handler.go | 36 +++++++++++++-
core/api/internal/space/model.go | 8 ++--
core/api/internal/space/service.go | 52 +++++++++++++++++---
core/api/server/router.go | 1 +
7 files changed, 250 insertions(+), 49 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 66823dff8e..75a4a45c81 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -253,7 +253,7 @@ const docTemplate = `{
"200": {
"description": "Space created successfully",
"schema": {
- "$ref": "#/definitions/space.CreateSpaceResponse"
+ "$ref": "#/definitions/space.SpaceResponse"
}
},
"400": {
@@ -283,6 +283,55 @@ const docTemplate = `{
}
}
},
+ "/spaces/{space_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get space",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Space",
+ "schema": {
+ "$ref": "#/definitions/space.SpaceResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Space not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
"/spaces/{space_id}/members": {
"get": {
"consumes": [
@@ -1556,19 +1605,6 @@ const docTemplate = `{
}
}
},
- "space.CreateSpaceResponse": {
- "type": "object",
- "properties": {
- "space": {
- "description": "The created space",
- "allOf": [
- {
- "$ref": "#/definitions/space.Space"
- }
- ]
- }
- }
- },
"space.Member": {
"type": "object",
"properties": {
@@ -1715,6 +1751,19 @@ const docTemplate = `{
}
}
},
+ "space.SpaceResponse": {
+ "type": "object",
+ "properties": {
+ "space": {
+ "description": "The space",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Space"
+ }
+ ]
+ }
+ }
+ },
"util.ForbiddenError": {
"type": "object",
"properties": {
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index 13034aae6a..edc96b8e6e 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -247,7 +247,7 @@
"200": {
"description": "Space created successfully",
"schema": {
- "$ref": "#/definitions/space.CreateSpaceResponse"
+ "$ref": "#/definitions/space.SpaceResponse"
}
},
"400": {
@@ -277,6 +277,55 @@
}
}
},
+ "/spaces/{space_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get space",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Space",
+ "schema": {
+ "$ref": "#/definitions/space.SpaceResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Space not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
"/spaces/{space_id}/members": {
"get": {
"consumes": [
@@ -1550,19 +1599,6 @@
}
}
},
- "space.CreateSpaceResponse": {
- "type": "object",
- "properties": {
- "space": {
- "description": "The created space",
- "allOf": [
- {
- "$ref": "#/definitions/space.Space"
- }
- ]
- }
- }
- },
"space.Member": {
"type": "object",
"properties": {
@@ -1709,6 +1745,19 @@
}
}
},
+ "space.SpaceResponse": {
+ "type": "object",
+ "properties": {
+ "space": {
+ "description": "The space",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Space"
+ }
+ ]
+ }
+ }
+ },
"util.ForbiddenError": {
"type": "object",
"properties": {
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 29f3e2d8f2..5e5dd22fbe 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -427,13 +427,6 @@ definitions:
example: New Space
type: string
type: object
- space.CreateSpaceResponse:
- properties:
- space:
- allOf:
- - $ref: '#/definitions/space.Space'
- description: The created space
- type: object
space.Member:
properties:
global_name:
@@ -550,6 +543,13 @@ definitions:
example: bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y
type: string
type: object
+ space.SpaceResponse:
+ properties:
+ space:
+ allOf:
+ - $ref: '#/definitions/space.Space'
+ description: The space
+ type: object
util.ForbiddenError:
properties:
error:
@@ -775,7 +775,7 @@ paths:
"200":
description: Space created successfully
schema:
- $ref: '#/definitions/space.CreateSpaceResponse'
+ $ref: '#/definitions/space.SpaceResponse'
"400":
description: Bad request
schema:
@@ -795,6 +795,38 @@ paths:
summary: Create space
tags:
- spaces
+ /spaces/{space_id}:
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: Space
+ schema:
+ $ref: '#/definitions/space.SpaceResponse'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Space not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Get space
+ tags:
+ - spaces
/spaces/{space_id}/members:
get:
consumes:
diff --git a/core/api/internal/space/handler.go b/core/api/internal/space/handler.go
index 962423a3e0..9aa63043c1 100644
--- a/core/api/internal/space/handler.go
+++ b/core/api/internal/space/handler.go
@@ -42,6 +42,38 @@ func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
}
}
+// GetSpaceHandler retrieves a space
+//
+// @Summary Get space
+// @Tags spaces
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Success 200 {object} SpaceResponse "Space"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Space not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /spaces/{space_id} [get]
+func GetSpaceHandler(s *SpaceService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceId := c.Param("space_id")
+
+ space, err := s.GetSpace(c.Request.Context(), spaceId)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrWorkspaceNotFound, http.StatusNotFound),
+ util.ErrToCode(ErrFailedOpenWorkspace, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ c.JSON(http.StatusOK, SpaceResponse{Space: space})
+ }
+}
+
// CreateSpaceHandler creates a new space
//
// @Summary Create space
@@ -49,7 +81,7 @@ func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
// @Accept json
// @Produce json
// @Param name body CreateSpaceRequest true "Space to create"
-// @Success 200 {object} CreateSpaceResponse "Space created successfully"
+// @Success 200 {object} SpaceResponse "Space created successfully"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
@@ -75,7 +107,7 @@ func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
return
}
- c.JSON(http.StatusOK, CreateSpaceResponse{Space: space})
+ c.JSON(http.StatusOK, SpaceResponse{Space: space})
}
}
diff --git a/core/api/internal/space/model.go b/core/api/internal/space/model.go
index 73cbe732be..877978edcd 100644
--- a/core/api/internal/space/model.go
+++ b/core/api/internal/space/model.go
@@ -1,11 +1,11 @@
package space
-type CreateSpaceRequest struct {
- Name string `json:"name" example:"New Space"` // The name of the space
+type SpaceResponse struct {
+ Space Space `json:"space"` // The space
}
-type CreateSpaceResponse struct {
- Space Space `json:"space"` // The created space
+type CreateSpaceRequest struct {
+ Name string `json:"name" example:"New Space"` // The name of the space
}
type Space struct {
diff --git a/core/api/internal/space/service.go b/core/api/internal/space/service.go
index 9a617b8472..a997e43cc1 100644
--- a/core/api/internal/space/service.go
+++ b/core/api/internal/space/service.go
@@ -20,6 +20,7 @@ import (
var (
ErrFailedListSpaces = errors.New("failed to retrieve list of spaces")
ErrFailedOpenWorkspace = errors.New("failed to open workspace")
+ ErrWorkspaceNotFound = errors.New("workspace not found")
ErrFailedGenerateRandomIcon = errors.New("failed to generate random icon")
ErrFailedCreateSpace = errors.New("failed to create space")
ErrFailedListMembers = errors.New("failed to retrieve list of members")
@@ -27,6 +28,7 @@ var (
type Service interface {
ListSpaces(ctx context.Context, offset int, limit int) ([]Space, int, bool, error)
+ GetSpace(ctx context.Context, spaceId string) (Space, error)
CreateSpace(ctx context.Context, name string) (Space, error)
ListMembers(ctx context.Context, spaceId string, offset int, limit int) ([]Member, int, bool, error)
}
@@ -78,21 +80,55 @@ func (s *SpaceService) ListSpaces(ctx context.Context, offset int, limit int) (s
spaces = make([]Space, 0, len(paginatedRecords))
for _, record := range paginatedRecords {
- workspace, err := s.getWorkspaceInfo(record.Fields[bundle.RelationKeyTargetSpaceId.String()].GetStringValue())
+ name := record.Fields[bundle.RelationKeyName.String()].GetStringValue()
+ icon := util.GetIconFromEmojiOrImage(s.AccountInfo, record.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), record.Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
+
+ workspace, err := s.getWorkspaceInfo(record.Fields[bundle.RelationKeyTargetSpaceId.String()].GetStringValue(), name, icon)
if err != nil {
return nil, 0, false, err
}
- // TODO: name and icon are only returned here; fix that
- workspace.Name = record.Fields[bundle.RelationKeyName.String()].GetStringValue()
- workspace.Icon = util.GetIconFromEmojiOrImage(s.AccountInfo, record.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), record.Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
-
spaces = append(spaces, workspace)
}
return spaces, total, hasMore, nil
}
+// GetSpace returns the space info for the space with the given ID.
+func (s *SpaceService) GetSpace(ctx context.Context, spaceId string) (Space, error) {
+ // Check if the workspace exists and is active
+ resp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
+ SpaceId: s.AccountInfo.TechSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyTargetSpaceId.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String(spaceId),
+ },
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeySpaceLocalStatus.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.Int64(int64(model.SpaceStatus_Ok)),
+ },
+ },
+ Keys: []string{bundle.RelationKeyTargetSpaceId.String()},
+ })
+
+ if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
+ return Space{}, ErrFailedOpenWorkspace
+ }
+
+ if len(resp.Records) == 0 {
+ return Space{}, ErrWorkspaceNotFound
+ }
+
+ name := resp.Records[0].Fields[bundle.RelationKeyName.String()].GetStringValue()
+ icon := util.GetIconFromEmojiOrImage(s.AccountInfo, resp.Records[0].Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), resp.Records[0].Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
+ return s.getWorkspaceInfo(spaceId, name, icon)
+}
+
// CreateSpace creates a new space with the given name and returns the space info.
func (s *SpaceService) CreateSpace(ctx context.Context, name string) (Space, error) {
iconOption, err := rand.Int(rand.Reader, big.NewInt(13))
@@ -117,7 +153,7 @@ func (s *SpaceService) CreateSpace(ctx context.Context, name string) (Space, err
return Space{}, ErrFailedCreateSpace
}
- return s.getWorkspaceInfo(resp.SpaceId)
+ return s.getWorkspaceInfo(resp.SpaceId, name, "")
}
// ListMembers returns a paginated list of members in the space with the given ID.
@@ -210,7 +246,7 @@ func (s *SpaceService) GetParticipantDetails(mw service.ClientCommandsServer, sp
}
// getWorkspaceInfo returns the workspace info for the space with the given ID.
-func (s *SpaceService) getWorkspaceInfo(spaceId string) (space Space, err error) {
+func (s *SpaceService) getWorkspaceInfo(spaceId string, name string, icon string) (space Space, err error) {
workspaceResponse := s.mw.WorkspaceOpen(context.Background(), &pb.RpcWorkspaceOpenRequest{
SpaceId: spaceId,
WithChat: true,
@@ -223,6 +259,8 @@ func (s *SpaceService) getWorkspaceInfo(spaceId string) (space Space, err error)
return Space{
Type: "space",
Id: spaceId,
+ Name: name,
+ Icon: icon,
HomeObjectId: workspaceResponse.Info.HomeObjectId,
ArchiveObjectId: workspaceResponse.Info.ArchiveObjectId,
ProfileObjectId: workspaceResponse.Info.ProfileObjectId,
diff --git a/core/api/server/router.go b/core/api/server/router.go
index e33206a325..d0467e9360 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -78,6 +78,7 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
// Space
v1.GET("/spaces", space.GetSpacesHandler(s.spaceService))
+ v1.GET("/spaces/:space_id", space.GetSpaceHandler(s.spaceService))
v1.GET("/spaces/:space_id/members", space.GetMembersHandler(s.spaceService))
v1.POST("/spaces", s.rateLimit(maxWriteRequestsPerSecond), space.CreateSpaceHandler(s.spaceService))
From da5299019d9ced4e406d4341e43fe1ffec812736 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 9 Feb 2025 19:02:18 +0100
Subject: [PATCH 07/31] GO-4459: Add missing relation keys in GetSpace
---
core/api/internal/space/service.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/api/internal/space/service.go b/core/api/internal/space/service.go
index a997e43cc1..b9c27bb576 100644
--- a/core/api/internal/space/service.go
+++ b/core/api/internal/space/service.go
@@ -113,7 +113,7 @@ func (s *SpaceService) GetSpace(ctx context.Context, spaceId string) (Space, err
Value: pbtypes.Int64(int64(model.SpaceStatus_Ok)),
},
},
- Keys: []string{bundle.RelationKeyTargetSpaceId.String()},
+ Keys: []string{bundle.RelationKeyTargetSpaceId.String(), bundle.RelationKeyName.String(), bundle.RelationKeyIconEmoji.String(), bundle.RelationKeyIconImage.String()},
})
if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
From 2010b1a2a37c3708b3782ce59e5ebc7ccc75e9a1 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 9 Feb 2025 19:31:07 +0100
Subject: [PATCH 08/31] GO-4459: Add endpoint for single member
---
core/api/docs/docs.go | 69 +++++++++++++++++++++++++++++
core/api/docs/swagger.json | 69 +++++++++++++++++++++++++++++
core/api/docs/swagger.yaml | 44 ++++++++++++++++++
core/api/internal/object/service.go | 14 +++++-
core/api/internal/space/handler.go | 34 ++++++++++++++
core/api/internal/space/model.go | 4 ++
core/api/internal/space/service.go | 16 ++++---
core/api/server/router.go | 1 +
8 files changed, 243 insertions(+), 8 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 75a4a45c81..79214ab946 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -390,6 +390,62 @@ const docTemplate = `{
}
}
},
+ "/spaces/{space_id}/members/{member_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get member",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "Member ID",
+ "name": "member_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Member",
+ "schema": {
+ "$ref": "#/definitions/space.MemberResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Member not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
"/spaces/{space_id}/objects": {
"get": {
"consumes": [
@@ -1651,6 +1707,19 @@ const docTemplate = `{
}
}
},
+ "space.MemberResponse": {
+ "type": "object",
+ "properties": {
+ "member": {
+ "description": "The member",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Member"
+ }
+ ]
+ }
+ }
+ },
"space.Space": {
"type": "object",
"properties": {
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index edc96b8e6e..7978d53c05 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -384,6 +384,62 @@
}
}
},
+ "/spaces/{space_id}/members/{member_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get member",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "Member ID",
+ "name": "member_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Member",
+ "schema": {
+ "$ref": "#/definitions/space.MemberResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Member not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
"/spaces/{space_id}/objects": {
"get": {
"consumes": [
@@ -1645,6 +1701,19 @@
}
}
},
+ "space.MemberResponse": {
+ "type": "object",
+ "properties": {
+ "member": {
+ "description": "The member",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Member"
+ }
+ ]
+ }
+ }
+ },
"space.Space": {
"type": "object",
"properties": {
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 5e5dd22fbe..1f1b9a7690 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -463,6 +463,13 @@ definitions:
example: member
type: string
type: object
+ space.MemberResponse:
+ properties:
+ member:
+ allOf:
+ - $ref: '#/definitions/space.Member'
+ description: The member
+ type: object
space.Space:
properties:
account_space_id:
@@ -867,6 +874,43 @@ paths:
summary: List members
tags:
- spaces
+ /spaces/{space_id}/members/{member_id}:
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ - description: Member ID
+ in: path
+ name: member_id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: Member
+ schema:
+ $ref: '#/definitions/space.MemberResponse'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Member not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Get member
+ tags:
+ - spaces
/spaces/{space_id}/objects:
get:
consumes:
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 91efda7b20..284a588ad3 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -447,6 +447,16 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
}
}
+ memberLastModifiedBy, err := s.spaceService.GetMember(context.Background(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), lastModifiedById)
+ if err != nil {
+ memberLastModifiedBy = space.Member{}
+ }
+
+ memberCreator, err := s.spaceService.GetMember(context.Background(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), creatorId)
+ if err != nil {
+ memberCreator = space.Member{}
+ }
+
return []Detail{
{
Id: "last_modified_date",
@@ -457,7 +467,7 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
{
Id: "last_modified_by",
Details: map[string]interface{}{
- "details": s.spaceService.GetParticipantDetails(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), lastModifiedById),
+ "details": memberLastModifiedBy,
},
},
{
@@ -469,7 +479,7 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
{
Id: "created_by",
Details: map[string]interface{}{
- "details": s.spaceService.GetParticipantDetails(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), creatorId),
+ "details": memberCreator,
},
},
{
diff --git a/core/api/internal/space/handler.go b/core/api/internal/space/handler.go
index 9aa63043c1..5dbbd2cd83 100644
--- a/core/api/internal/space/handler.go
+++ b/core/api/internal/space/handler.go
@@ -144,3 +144,37 @@ func GetMembersHandler(s *SpaceService) gin.HandlerFunc {
pagination.RespondWithPagination(c, http.StatusOK, members, total, offset, limit, hasMore)
}
}
+
+// GetMemberHandler retrieves a member in a space
+//
+// @Summary Get member
+// @Tags spaces
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param member_id path string true "Member ID"
+// @Success 200 {object} MemberResponse "Member"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Member not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /spaces/{space_id}/members/{member_id} [get]
+func GetMemberHandler(s *SpaceService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceId := c.Param("space_id")
+ memberId := c.Param("member_id")
+
+ member, err := s.GetMember(c.Request.Context(), spaceId, memberId)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrMemberNotFound, http.StatusNotFound),
+ util.ErrToCode(ErrFailedGetMember, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ c.JSON(http.StatusOK, MemberResponse{Member: member})
+ }
+}
diff --git a/core/api/internal/space/model.go b/core/api/internal/space/model.go
index 877978edcd..6805de3ccb 100644
--- a/core/api/internal/space/model.go
+++ b/core/api/internal/space/model.go
@@ -30,6 +30,10 @@ type Space struct {
NetworkId string `json:"network_id" example:"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"` // The network id of the space
}
+type MemberResponse struct {
+ Member Member `json:"member"` // The member
+}
+
type Member struct {
Type string `json:"type" example:"member"` // The type of the object
Id string `json:"id" example:"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"` // The profile object id of the member
diff --git a/core/api/internal/space/service.go b/core/api/internal/space/service.go
index b9c27bb576..eb83f636c7 100644
--- a/core/api/internal/space/service.go
+++ b/core/api/internal/space/service.go
@@ -24,6 +24,8 @@ var (
ErrFailedGenerateRandomIcon = errors.New("failed to generate random icon")
ErrFailedCreateSpace = errors.New("failed to create space")
ErrFailedListMembers = errors.New("failed to retrieve list of members")
+ ErrFailedGetMember = errors.New("failed to retrieve member")
+ ErrMemberNotFound = errors.New("member not found")
)
type Service interface {
@@ -31,6 +33,7 @@ type Service interface {
GetSpace(ctx context.Context, spaceId string) (Space, error)
CreateSpace(ctx context.Context, name string) (Space, error)
ListMembers(ctx context.Context, spaceId string, offset int, limit int) ([]Member, int, bool, error)
+ GetMember(ctx context.Context, spaceId string, memberId string) (Member, error)
}
type SpaceService struct {
@@ -210,26 +213,27 @@ func (s *SpaceService) ListMembers(ctx context.Context, spaceId string, offset i
return members, total, hasMore, nil
}
-func (s *SpaceService) GetParticipantDetails(mw service.ClientCommandsServer, spaceId string, participantId string) Member {
- resp := mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
+// GetMember returns the member with the given ID in the space with the given ID.
+func (s *SpaceService) GetMember(ctx context.Context, spaceId string, memberId string) (Member, error) {
+ resp := s.mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
SpaceId: spaceId,
Filters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyId.String(),
Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(participantId),
+ Value: pbtypes.String(memberId),
},
},
Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeyName.String(), bundle.RelationKeyIconEmoji.String(), bundle.RelationKeyIconImage.String(), bundle.RelationKeyIdentity.String(), bundle.RelationKeyGlobalName.String(), bundle.RelationKeyParticipantPermissions.String()},
})
if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
- return Member{}
+ return Member{}, ErrFailedGetMember
}
if len(resp.Records) == 0 {
- return Member{}
+ return Member{}, ErrMemberNotFound
}
icon := util.GetIconFromEmojiOrImage(s.AccountInfo, "", resp.Records[0].Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
@@ -242,7 +246,7 @@ func (s *SpaceService) GetParticipantDetails(mw service.ClientCommandsServer, sp
Identity: resp.Records[0].Fields[bundle.RelationKeyIdentity.String()].GetStringValue(),
GlobalName: resp.Records[0].Fields[bundle.RelationKeyGlobalName.String()].GetStringValue(),
Role: model.ParticipantPermissions_name[int32(resp.Records[0].Fields[bundle.RelationKeyParticipantPermissions.String()].GetNumberValue())],
- }
+ }, nil
}
// getWorkspaceInfo returns the workspace info for the space with the given ID.
diff --git a/core/api/server/router.go b/core/api/server/router.go
index d0467e9360..ed1b00a990 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -80,6 +80,7 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
v1.GET("/spaces", space.GetSpacesHandler(s.spaceService))
v1.GET("/spaces/:space_id", space.GetSpaceHandler(s.spaceService))
v1.GET("/spaces/:space_id/members", space.GetMembersHandler(s.spaceService))
+ v1.GET("/spaces/:space_id/members/:member_id", space.GetMemberHandler(s.spaceService))
v1.POST("/spaces", s.rateLimit(maxWriteRequestsPerSecond), space.CreateSpaceHandler(s.spaceService))
// Type
From 544d9488c7f8b4b7f42558348fb299e0bf1bc054 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Wed, 12 Feb 2025 12:17:47 +0100
Subject: [PATCH 09/31] GO-4459: Add handlers and routes for list endpoints
---
core/api/docs/docs.go | 285 ++++++++++++++++++++++++++++
core/api/docs/swagger.json | 285 ++++++++++++++++++++++++++++
core/api/docs/swagger.yaml | 191 +++++++++++++++++++
core/api/internal/export/service.go | 3 +-
core/api/internal/list/handler.go | 173 +++++++++++++++++
core/api/internal/list/service.go | 51 +++++
core/api/server/middleware.go | 1 -
core/api/server/router.go | 7 +
core/api/server/server.go | 3 +
9 files changed, 996 insertions(+), 3 deletions(-)
create mode 100644 core/api/internal/list/handler.go
create mode 100644 core/api/internal/list/service.go
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 79214ab946..8283877be5 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -1063,6 +1063,291 @@ const docTemplate = `{
}
}
}
+ },
+ "/v1/spaces/{space_id}/lists/{list_id}/objects": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Get objects in list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "default": 0,
+ "description": "The number of items to skip before starting to collect the result set",
+ "name": "offset",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "The number of items to return",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "List of objects",
+ "schema": {
+ "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Add objects to list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "List of object IDs",
+ "name": "objects",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Objects added successfully",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "Bad request",
+ "schema": {
+ "$ref": "#/definitions/util.ValidationError"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Remove objects from list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "List of object IDs",
+ "name": "objects",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Objects removed successfully",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "Bad request",
+ "schema": {
+ "$ref": "#/definitions/util.ValidationError"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Update object order in list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "List of object IDs",
+ "name": "objects",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Objects updated successfully",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "Bad request",
+ "schema": {
+ "$ref": "#/definitions/util.ValidationError"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
}
},
"definitions": {
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index 7978d53c05..2de24feafc 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -1057,6 +1057,291 @@
}
}
}
+ },
+ "/v1/spaces/{space_id}/lists/{list_id}/objects": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Get objects in list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "default": 0,
+ "description": "The number of items to skip before starting to collect the result set",
+ "name": "offset",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "The number of items to return",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "List of objects",
+ "schema": {
+ "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Add objects to list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "List of object IDs",
+ "name": "objects",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Objects added successfully",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "Bad request",
+ "schema": {
+ "$ref": "#/definitions/util.ValidationError"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Remove objects from list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "List of object IDs",
+ "name": "objects",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Objects removed successfully",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "Bad request",
+ "schema": {
+ "$ref": "#/definitions/util.ValidationError"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "list"
+ ],
+ "summary": "Update object order in list",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "List ID",
+ "name": "list_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "List of object IDs",
+ "name": "objects",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Objects updated successfully",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "Bad request",
+ "schema": {
+ "$ref": "#/definitions/util.ValidationError"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
}
},
"definitions": {
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 1f1b9a7690..61b43ac732 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -1328,6 +1328,197 @@ paths:
summary: Get template
tags:
- types
+ /v1/spaces/{space_id}/lists/{list_id}/objects:
+ delete:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ - description: List ID
+ in: path
+ name: list_id
+ required: true
+ type: string
+ - description: List of object IDs
+ in: body
+ name: objects
+ required: true
+ schema:
+ items:
+ type: string
+ type: array
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: Objects removed successfully
+ schema:
+ type: string
+ "400":
+ description: Bad request
+ schema:
+ $ref: '#/definitions/util.ValidationError'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Remove objects from list
+ tags:
+ - list
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ - description: List ID
+ in: path
+ name: list_id
+ required: true
+ type: string
+ - default: 0
+ description: The number of items to skip before starting to collect the result
+ set
+ in: query
+ name: offset
+ type: integer
+ - description: The number of items to return
+ in: query
+ name: limit
+ type: integer
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: List of objects
+ schema:
+ $ref: '#/definitions/pagination.PaginatedResponse-object_Object'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Get objects in list
+ tags:
+ - list
+ patch:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ - description: List ID
+ in: path
+ name: list_id
+ required: true
+ type: string
+ - description: List of object IDs
+ in: body
+ name: objects
+ required: true
+ schema:
+ items:
+ type: string
+ type: array
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: Objects updated successfully
+ schema:
+ type: string
+ "400":
+ description: Bad request
+ schema:
+ $ref: '#/definitions/util.ValidationError'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Update object order in list
+ tags:
+ - list
+ post:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ - description: List ID
+ in: path
+ name: list_id
+ required: true
+ type: string
+ - description: List of object IDs
+ in: body
+ name: objects
+ required: true
+ schema:
+ items:
+ type: string
+ type: array
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: Objects added successfully
+ schema:
+ type: string
+ "400":
+ description: Bad request
+ schema:
+ $ref: '#/definitions/util.ValidationError'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Add objects to list
+ tags:
+ - list
securityDefinitions:
BasicAuth:
type: basic
diff --git a/core/api/internal/export/service.go b/core/api/internal/export/service.go
index b20361351c..bcb4e4e338 100644
--- a/core/api/internal/export/service.go
+++ b/core/api/internal/export/service.go
@@ -19,8 +19,7 @@ type Service interface {
}
type ExportService struct {
- mw service.ClientCommandsServer
- AccountInfo *model.AccountInfo
+ mw service.ClientCommandsServer
}
func NewService(mw service.ClientCommandsServer) *ExportService {
diff --git a/core/api/internal/list/handler.go b/core/api/internal/list/handler.go
new file mode 100644
index 0000000000..f7e6ad959d
--- /dev/null
+++ b/core/api/internal/list/handler.go
@@ -0,0 +1,173 @@
+package list
+
+import (
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+
+ "github.com/anyproto/anytype-heart/core/api/pagination"
+ "github.com/anyproto/anytype-heart/core/api/util"
+)
+
+// GetObjectsInListHandler
+//
+// @Summary Get objects in list
+// @Tags list
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param list_id path string true "List ID"
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return"
+// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [get]
+func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceID := c.Param("space_id")
+ listID := c.Param("list_id")
+ offset := c.GetInt("offset")
+ limit := c.GetInt("limit")
+
+ objects, total, hasMore, err := s.GetObjectsInList(c, spaceID, listID, offset, limit)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrFailedGetObjectsInList, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ pagination.RespondWithPagination(c, http.StatusOK, objects, total, offset, limit, hasMore)
+ }
+}
+
+// AddObjectsToListHandler
+//
+// @Summary Add objects to list
+// @Tags list
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param list_id path string true "List ID"
+// @Param objects body []string true "List of object IDs"
+// @Success 200 {object} string "Objects added successfully"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [post]
+func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceID := c.Param("space_id")
+ listID := c.Param("list_id")
+
+ objects := []string{}
+ if err := c.ShouldBindJSON(&objects); err != nil {
+ apiErr := util.CodeToAPIError(http.StatusBadRequest, err.Error())
+ c.JSON(http.StatusBadRequest, apiErr)
+ return
+ }
+
+ err := s.AddObjectsToList(c, spaceID, listID, objects)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrFailedAddObjectsToList, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ c.JSON(http.StatusOK, "Objects added successfully")
+ }
+}
+
+// RemoveObjectsFromListHandler
+//
+// @Summary Remove objects from list
+// @Tags list
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param list_id path string true "List ID"
+// @Param objects body []string true "List of object IDs"
+// @Success 200 {object} string "Objects removed successfully"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [delete]
+func RemoveObjectsFromListHandler(s *ListService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceID := c.Param("space_id")
+ listID := c.Param("list_id")
+
+ objects := []string{}
+ if err := c.ShouldBindJSON(&objects); err != nil {
+ apiErr := util.CodeToAPIError(http.StatusBadRequest, err.Error())
+ c.JSON(http.StatusBadRequest, apiErr)
+ return
+ }
+
+ err := s.RemoveObjectsFromList(c, spaceID, listID, objects)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrFailedRemoveObjectsFromList, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ c.JSON(http.StatusOK, "Objects removed successfully")
+ }
+}
+
+// UpdateObjectsInListHandler
+//
+// @Summary Update object order in list
+// @Tags list
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param list_id path string true "List ID"
+// @Param objects body []string true "List of object IDs"
+// @Success 200 {object} string "Objects updated successfully"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [patch]
+func UpdateObjectsInListHandler(s *ListService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceID := c.Param("space_id")
+ listID := c.Param("list_id")
+
+ objects := []string{}
+ if err := c.ShouldBindJSON(&objects); err != nil {
+ apiErr := util.CodeToAPIError(http.StatusBadRequest, err.Error())
+ c.JSON(http.StatusBadRequest, apiErr)
+ return
+ }
+
+ err := s.UpdateObjectsInList(c, spaceID, listID, objects)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrFailedUpdateObjectsInList, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ c.JSON(http.StatusOK, "Objects updated successfully")
+ }
+}
diff --git a/core/api/internal/list/service.go b/core/api/internal/list/service.go
new file mode 100644
index 0000000000..b55868718d
--- /dev/null
+++ b/core/api/internal/list/service.go
@@ -0,0 +1,51 @@
+package list
+
+import (
+ "context"
+ "errors"
+
+ "github.com/anyproto/anytype-heart/pb/service"
+ "github.com/anyproto/anytype-heart/pkg/lib/pb/model"
+)
+
+var (
+ ErrFailedGetObjectsInList = errors.New("failed to get objects in list")
+ ErrFailedAddObjectsToList = errors.New("failed to add objects to list")
+ ErrFailedRemoveObjectsFromList = errors.New("failed to remove objects from list")
+ ErrFailedUpdateObjectsInList = errors.New("failed to update objects in list")
+)
+
+type Service interface {
+ GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]*model.Object, int, bool, error)
+ AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIDs []string) error
+ RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIDs []string) error
+ UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIDs []string) error
+}
+
+type ListService struct {
+ mw service.ClientCommandsServer
+}
+
+func NewService(mw service.ClientCommandsServer) *ListService {
+ return &ListService{mw: mw}
+}
+
+// GetObjectsInList retrieves objects in a list
+func (s *ListService) GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]*model.Object, int, bool, error) {
+ return nil, 0, false, nil
+}
+
+// AddObjectsToList adds objects to a list
+func (s *ListService) AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIDs []string) error {
+ return nil
+}
+
+// RemoveObjectsFromList removes objects from a list
+func (s *ListService) RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIDs []string) error {
+ return nil
+}
+
+// UpdateObjectsInList updates an object in a list
+func (s *ListService) UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIDs []string) error {
+ return nil
+}
diff --git a/core/api/server/middleware.go b/core/api/server/middleware.go
index d2a2d23c94..1313127f80 100644
--- a/core/api/server/middleware.go
+++ b/core/api/server/middleware.go
@@ -88,7 +88,6 @@ func (s *Server) ensureAccountInfo(accountService account.Service) gin.HandlerFu
return
}
- s.exportService.AccountInfo = accInfo
s.objectService.AccountInfo = accInfo
s.spaceService.AccountInfo = accInfo
s.searchService.AccountInfo = accInfo
diff --git a/core/api/server/router.go b/core/api/server/router.go
index ed1b00a990..f7aad0482d 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -12,6 +12,7 @@ import (
"github.com/anyproto/anytype-heart/core/anytype/account"
"github.com/anyproto/anytype-heart/core/api/internal/auth"
"github.com/anyproto/anytype-heart/core/api/internal/export"
+ "github.com/anyproto/anytype-heart/core/api/internal/list"
"github.com/anyproto/anytype-heart/core/api/internal/object"
"github.com/anyproto/anytype-heart/core/api/internal/search"
"github.com/anyproto/anytype-heart/core/api/internal/space"
@@ -66,6 +67,12 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
// Export
v1.POST("/spaces/:space_id/objects/:object_id/export/:format", export.GetObjectExportHandler(s.exportService))
+ // List
+ v1.GET("/v1/spaces/:space_id/lists/:list_id/objects", list.GetObjectsInListHandler(s.listService))
+ v1.POST("/v1/spaces/:space_id/lists/:list_id/objects", list.AddObjectsToListHandler(s.listService))
+ v1.DELETE("/v1/spaces/:space_id/lists/:list_id/objects", list.RemoveObjectsFromListHandler(s.listService))
+ v1.PATCH("/v1/spaces/:space_id/lists/:list_id/objects", list.UpdateObjectsInListHandler(s.listService))
+
// Object
v1.GET("/spaces/:space_id/objects", object.GetObjectsHandler(s.objectService))
v1.GET("/spaces/:space_id/objects/:object_id", object.GetObjectHandler(s.objectService))
diff --git a/core/api/server/server.go b/core/api/server/server.go
index 78fb467932..56b312d699 100644
--- a/core/api/server/server.go
+++ b/core/api/server/server.go
@@ -8,6 +8,7 @@ import (
"github.com/anyproto/anytype-heart/core/anytype/account"
"github.com/anyproto/anytype-heart/core/api/internal/auth"
"github.com/anyproto/anytype-heart/core/api/internal/export"
+ "github.com/anyproto/anytype-heart/core/api/internal/list"
"github.com/anyproto/anytype-heart/core/api/internal/object"
"github.com/anyproto/anytype-heart/core/api/internal/search"
"github.com/anyproto/anytype-heart/core/api/internal/space"
@@ -20,6 +21,7 @@ type Server struct {
authService *auth.AuthService
exportService *export.ExportService
+ listService *list.ListService
objectService *object.ObjectService
spaceService *space.SpaceService
searchService *search.SearchService
@@ -33,6 +35,7 @@ func NewServer(accountService account.Service, mw service.ClientCommandsServer)
s := &Server{
authService: auth.NewService(mw),
exportService: export.NewService(mw),
+ listService: list.NewService(mw),
spaceService: space.NewService(mw),
}
From 526de3ccd31f407213316ab61867c3f0e39e186f Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Wed, 12 Feb 2025 15:47:05 +0100
Subject: [PATCH 10/31] GO-4459: Add initial list service implementation
---
core/api/docs/docs.go | 8 +--
core/api/docs/swagger.json | 8 +--
core/api/docs/swagger.yaml | 8 +--
core/api/internal/list/handler.go | 32 ++++++------
core/api/internal/list/service.go | 85 +++++++++++++++++++++++++++----
core/api/server/server.go | 2 +-
6 files changed, 103 insertions(+), 40 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 8283877be5..f158831eb6 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -1073,7 +1073,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Get objects in list",
"parameters": [
@@ -1140,7 +1140,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Add objects to list",
"parameters": [
@@ -1212,7 +1212,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Remove objects from list",
"parameters": [
@@ -1284,7 +1284,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Update object order in list",
"parameters": [
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index 2de24feafc..0d063df110 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -1067,7 +1067,7 @@
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Get objects in list",
"parameters": [
@@ -1134,7 +1134,7 @@
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Add objects to list",
"parameters": [
@@ -1206,7 +1206,7 @@
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Remove objects from list",
"parameters": [
@@ -1278,7 +1278,7 @@
"application/json"
],
"tags": [
- "list"
+ "lists"
],
"summary": "Update object order in list",
"parameters": [
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 61b43ac732..5f31973fac 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -1376,7 +1376,7 @@ paths:
$ref: '#/definitions/util.ServerError'
summary: Remove objects from list
tags:
- - list
+ - lists
get:
consumes:
- application/json
@@ -1422,7 +1422,7 @@ paths:
$ref: '#/definitions/util.ServerError'
summary: Get objects in list
tags:
- - list
+ - lists
patch:
consumes:
- application/json
@@ -1470,7 +1470,7 @@ paths:
$ref: '#/definitions/util.ServerError'
summary: Update object order in list
tags:
- - list
+ - lists
post:
consumes:
- application/json
@@ -1518,7 +1518,7 @@ paths:
$ref: '#/definitions/util.ServerError'
summary: Add objects to list
tags:
- - list
+ - lists
securityDefinitions:
BasicAuth:
type: basic
diff --git a/core/api/internal/list/handler.go b/core/api/internal/list/handler.go
index f7e6ad959d..e1e7fbd75c 100644
--- a/core/api/internal/list/handler.go
+++ b/core/api/internal/list/handler.go
@@ -12,7 +12,7 @@ import (
// GetObjectsInListHandler
//
// @Summary Get objects in list
-// @Tags list
+// @Tags lists
// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
@@ -26,12 +26,12 @@ import (
// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [get]
func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
- spaceID := c.Param("space_id")
- listID := c.Param("list_id")
+ spaceId := c.Param("space_id")
+ listId := c.Param("list_id")
offset := c.GetInt("offset")
limit := c.GetInt("limit")
- objects, total, hasMore, err := s.GetObjectsInList(c, spaceID, listID, offset, limit)
+ objects, total, hasMore, err := s.GetObjectsInList(c, spaceId, listId, offset, limit)
code := util.MapErrorCode(err,
util.ErrToCode(ErrFailedGetObjectsInList, http.StatusInternalServerError),
)
@@ -49,7 +49,7 @@ func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
// AddObjectsToListHandler
//
// @Summary Add objects to list
-// @Tags list
+// @Tags lists
// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
@@ -63,8 +63,8 @@ func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [post]
func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
- spaceID := c.Param("space_id")
- listID := c.Param("list_id")
+ spaceId := c.Param("space_id")
+ listId := c.Param("list_id")
objects := []string{}
if err := c.ShouldBindJSON(&objects); err != nil {
@@ -73,7 +73,7 @@ func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
return
}
- err := s.AddObjectsToList(c, spaceID, listID, objects)
+ err := s.AddObjectsToList(c, spaceId, listId, objects)
code := util.MapErrorCode(err,
util.ErrToCode(ErrFailedAddObjectsToList, http.StatusInternalServerError),
)
@@ -91,7 +91,7 @@ func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
// RemoveObjectsFromListHandler
//
// @Summary Remove objects from list
-// @Tags list
+// @Tags lists
// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
@@ -105,8 +105,8 @@ func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [delete]
func RemoveObjectsFromListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
- spaceID := c.Param("space_id")
- listID := c.Param("list_id")
+ spaceId := c.Param("space_id")
+ listId := c.Param("list_id")
objects := []string{}
if err := c.ShouldBindJSON(&objects); err != nil {
@@ -115,7 +115,7 @@ func RemoveObjectsFromListHandler(s *ListService) gin.HandlerFunc {
return
}
- err := s.RemoveObjectsFromList(c, spaceID, listID, objects)
+ err := s.RemoveObjectsFromList(c, spaceId, listId, objects)
code := util.MapErrorCode(err,
util.ErrToCode(ErrFailedRemoveObjectsFromList, http.StatusInternalServerError),
)
@@ -133,7 +133,7 @@ func RemoveObjectsFromListHandler(s *ListService) gin.HandlerFunc {
// UpdateObjectsInListHandler
//
// @Summary Update object order in list
-// @Tags list
+// @Tags lists
// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
@@ -147,8 +147,8 @@ func RemoveObjectsFromListHandler(s *ListService) gin.HandlerFunc {
// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [patch]
func UpdateObjectsInListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
- spaceID := c.Param("space_id")
- listID := c.Param("list_id")
+ spaceId := c.Param("space_id")
+ listId := c.Param("list_id")
objects := []string{}
if err := c.ShouldBindJSON(&objects); err != nil {
@@ -157,7 +157,7 @@ func UpdateObjectsInListHandler(s *ListService) gin.HandlerFunc {
return
}
- err := s.UpdateObjectsInList(c, spaceID, listID, objects)
+ err := s.UpdateObjectsInList(c, spaceId, listId, objects)
code := util.MapErrorCode(err,
util.ErrToCode(ErrFailedUpdateObjectsInList, http.StatusInternalServerError),
)
diff --git a/core/api/internal/list/service.go b/core/api/internal/list/service.go
index b55868718d..943035c440 100644
--- a/core/api/internal/list/service.go
+++ b/core/api/internal/list/service.go
@@ -4,7 +4,11 @@ import (
"context"
"errors"
+ "github.com/anyproto/anytype-heart/core/api/internal/object"
+ "github.com/anyproto/anytype-heart/core/api/pagination"
+ "github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb/service"
+ "github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
)
@@ -17,35 +21,94 @@ var (
type Service interface {
GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]*model.Object, int, bool, error)
- AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIDs []string) error
- RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIDs []string) error
- UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIDs []string) error
+ AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIds []string) error
+ RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIds []string) error
+ UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIds []string) error
}
type ListService struct {
- mw service.ClientCommandsServer
+ mw service.ClientCommandsServer
+ objectService *object.ObjectService
}
-func NewService(mw service.ClientCommandsServer) *ListService {
- return &ListService{mw: mw}
+func NewService(mw service.ClientCommandsServer, objectService *object.ObjectService) *ListService {
+ return &ListService{mw: mw, objectService: objectService}
}
// GetObjectsInList retrieves objects in a list
-func (s *ListService) GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]*model.Object, int, bool, error) {
- return nil, 0, false, nil
+func (s *ListService) GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]object.Object, int, bool, error) {
+ resp := s.mw.ObjectSearchSubscribe(ctx, &pb.RpcObjectSearchSubscribeRequest{
+ SpaceId: spaceId,
+ Limit: int64(limit), // nolint: gosec
+ Offset: int64(offset), // nolint: gosec
+ Keys: []string{bundle.RelationKeyId.String()},
+ CollectionId: listId,
+ })
+
+ if resp.Error.Code != pb.RpcObjectSearchSubscribeResponseError_NULL {
+ return nil, 0, false, ErrFailedGetObjectsInList
+ }
+
+ total := int(resp.Counters.Total)
+ paginatedRecords, hasMore := pagination.Paginate(resp.Records, offset, limit)
+
+ objects := make([]object.Object, 0, len(paginatedRecords))
+ for _, record := range paginatedRecords {
+ object, err := s.objectService.GetObject(ctx, spaceId, record.Fields[bundle.RelationKeyId.String()].GetStringValue())
+ if err != nil {
+ return nil, 0, false, err
+ }
+ objects = append(objects, object)
+ }
+
+ return objects, total, hasMore, nil
}
// AddObjectsToList adds objects to a list
-func (s *ListService) AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIDs []string) error {
+func (s *ListService) AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIds []string) error {
+ resp := s.mw.ObjectCollectionAdd(ctx, &pb.RpcObjectCollectionAddRequest{
+ ContextId: listId,
+ ObjectIds: objectIds,
+ })
+
+ if resp.Error.Code != pb.RpcObjectCollectionAddResponseError_NULL {
+ return ErrFailedAddObjectsToList
+ }
+
return nil
}
// RemoveObjectsFromList removes objects from a list
-func (s *ListService) RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIDs []string) error {
+func (s *ListService) RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIds []string) error {
+ resp := s.mw.ObjectCollectionRemove(ctx, &pb.RpcObjectCollectionRemoveRequest{
+ ContextId: spaceId,
+ ObjectIds: objectIds,
+ })
+
+ if resp.Error.Code != pb.RpcObjectCollectionRemoveResponseError_NULL {
+ return ErrFailedRemoveObjectsFromList
+ }
+
return nil
}
// UpdateObjectsInList updates an object in a list
-func (s *ListService) UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIDs []string) error {
+func (s *ListService) UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIds []string) error {
+ resp := s.mw.BlockDataviewObjectOrderUpdate(ctx, &pb.RpcBlockDataviewObjectOrderUpdateRequest{
+ ContextId: listId,
+ BlockId: "dataview",
+ ObjectOrders: []*model.BlockContentDataviewObjectOrder{
+ {
+ ViewId: "", // TODO: handle viewId
+ GroupId: "",
+ ObjectIds: objectIds,
+ },
+ },
+ })
+
+ if resp.Error.Code != pb.RpcBlockDataviewObjectOrderUpdateResponseError_NULL {
+ return ErrFailedUpdateObjectsInList
+ }
+
return nil
}
diff --git a/core/api/server/server.go b/core/api/server/server.go
index 56b312d699..f38dc6c7e7 100644
--- a/core/api/server/server.go
+++ b/core/api/server/server.go
@@ -35,11 +35,11 @@ func NewServer(accountService account.Service, mw service.ClientCommandsServer)
s := &Server{
authService: auth.NewService(mw),
exportService: export.NewService(mw),
- listService: list.NewService(mw),
spaceService: space.NewService(mw),
}
s.objectService = object.NewService(mw, s.spaceService)
+ s.listService = list.NewService(mw, s.objectService)
s.searchService = search.NewService(mw, s.spaceService, s.objectService)
s.engine = s.NewRouter(accountService, mw)
s.KeyToToken = make(map[string]string)
From 44b1bcc1da15e4b40f87cc92f32534cb24ab9717 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Wed, 12 Feb 2025 15:47:16 +0100
Subject: [PATCH 11/31] GO-4459: Fix v1 route path for lists
---
core/api/server/router.go | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/core/api/server/router.go b/core/api/server/router.go
index f7aad0482d..23d094bbb7 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -68,10 +68,10 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
v1.POST("/spaces/:space_id/objects/:object_id/export/:format", export.GetObjectExportHandler(s.exportService))
// List
- v1.GET("/v1/spaces/:space_id/lists/:list_id/objects", list.GetObjectsInListHandler(s.listService))
- v1.POST("/v1/spaces/:space_id/lists/:list_id/objects", list.AddObjectsToListHandler(s.listService))
- v1.DELETE("/v1/spaces/:space_id/lists/:list_id/objects", list.RemoveObjectsFromListHandler(s.listService))
- v1.PATCH("/v1/spaces/:space_id/lists/:list_id/objects", list.UpdateObjectsInListHandler(s.listService))
+ v1.GET("/spaces/:space_id/lists/:list_id/objects", list.GetObjectsInListHandler(s.listService))
+ v1.POST("/spaces/:space_id/lists/:list_id/objects", list.AddObjectsToListHandler(s.listService))
+ v1.DELETE("/spaces/:space_id/lists/:list_id/objects", list.RemoveObjectsFromListHandler(s.listService))
+ v1.PATCH("/spaces/:space_id/lists/:list_id/objects", list.UpdateObjectsInListHandler(s.listService))
// Object
v1.GET("/spaces/:space_id/objects", object.GetObjectsHandler(s.objectService))
From fd62a2571e39fb5b1c984868cecafb2f83648bf5 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 14 Feb 2025 16:04:56 +0100
Subject: [PATCH 12/31] GO-4459: Fix ObjectSearchSubscribe panic
---
core/api/internal/list/service.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/core/api/internal/list/service.go b/core/api/internal/list/service.go
index 943035c440..42be2f2f37 100644
--- a/core/api/internal/list/service.go
+++ b/core/api/internal/list/service.go
@@ -45,7 +45,8 @@ func (s *ListService) GetObjectsInList(ctx context.Context, spaceId string, list
CollectionId: listId,
})
- if resp.Error.Code != pb.RpcObjectSearchSubscribeResponseError_NULL {
+ // TODO: returned error from ObjectSearchSubscribe is inconsistent with other RPCs: Error is nil instead of Code being NULL
+ if resp.Error != nil && resp.Error.Code != pb.RpcObjectSearchSubscribeResponseError_NULL {
return nil, 0, false, ErrFailedGetObjectsInList
}
From dcb8a992f1e58bc20b29bfd4fc7a8fecc369c1b7 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 14 Feb 2025 16:10:48 +0100
Subject: [PATCH 13/31] GO-4459: Remove UpdateObjectsInList handler and route
---
core/api/docs/docs.go | 72 -------------------------------
core/api/docs/swagger.json | 72 -------------------------------
core/api/docs/swagger.yaml | 48 ---------------------
core/api/internal/list/handler.go | 42 ------------------
core/api/internal/list/service.go | 26 +----------
core/api/server/router.go | 1 -
6 files changed, 1 insertion(+), 260 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index f158831eb6..bc7016d05f 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -1275,78 +1275,6 @@ const docTemplate = `{
}
}
}
- },
- "patch": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Update object order in list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "description": "List of object IDs",
- "name": "objects",
- "in": "body",
- "required": true,
- "schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Objects updated successfully",
- "schema": {
- "type": "string"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
}
}
},
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index 0d063df110..d8ba3d1463 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -1269,78 +1269,6 @@
}
}
}
- },
- "patch": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Update object order in list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "description": "List of object IDs",
- "name": "objects",
- "in": "body",
- "required": true,
- "schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Objects updated successfully",
- "schema": {
- "type": "string"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
}
}
},
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 5f31973fac..46c1110f70 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -1423,54 +1423,6 @@ paths:
summary: Get objects in list
tags:
- lists
- patch:
- consumes:
- - application/json
- parameters:
- - description: Space ID
- in: path
- name: space_id
- required: true
- type: string
- - description: List ID
- in: path
- name: list_id
- required: true
- type: string
- - description: List of object IDs
- in: body
- name: objects
- required: true
- schema:
- items:
- type: string
- type: array
- produces:
- - application/json
- responses:
- "200":
- description: Objects updated successfully
- schema:
- type: string
- "400":
- description: Bad request
- schema:
- $ref: '#/definitions/util.ValidationError'
- "401":
- description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
- "404":
- description: Not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
- "500":
- description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
- summary: Update object order in list
- tags:
- - lists
post:
consumes:
- application/json
diff --git a/core/api/internal/list/handler.go b/core/api/internal/list/handler.go
index e1e7fbd75c..0830390f53 100644
--- a/core/api/internal/list/handler.go
+++ b/core/api/internal/list/handler.go
@@ -129,45 +129,3 @@ func RemoveObjectsFromListHandler(s *ListService) gin.HandlerFunc {
c.JSON(http.StatusOK, "Objects removed successfully")
}
}
-
-// UpdateObjectsInListHandler
-//
-// @Summary Update object order in list
-// @Tags lists
-// @Accept json
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param list_id path string true "List ID"
-// @Param objects body []string true "List of object IDs"
-// @Success 200 {object} string "Objects updated successfully"
-// @Failure 400 {object} util.ValidationError "Bad request"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [patch]
-func UpdateObjectsInListHandler(s *ListService) gin.HandlerFunc {
- return func(c *gin.Context) {
- spaceId := c.Param("space_id")
- listId := c.Param("list_id")
-
- objects := []string{}
- if err := c.ShouldBindJSON(&objects); err != nil {
- apiErr := util.CodeToAPIError(http.StatusBadRequest, err.Error())
- c.JSON(http.StatusBadRequest, apiErr)
- return
- }
-
- err := s.UpdateObjectsInList(c, spaceId, listId, objects)
- code := util.MapErrorCode(err,
- util.ErrToCode(ErrFailedUpdateObjectsInList, http.StatusInternalServerError),
- )
-
- if code != http.StatusOK {
- apiErr := util.CodeToAPIError(code, err.Error())
- c.JSON(code, apiErr)
- return
- }
-
- c.JSON(http.StatusOK, "Objects updated successfully")
- }
-}
diff --git a/core/api/internal/list/service.go b/core/api/internal/list/service.go
index 42be2f2f37..625e560506 100644
--- a/core/api/internal/list/service.go
+++ b/core/api/internal/list/service.go
@@ -9,21 +9,18 @@ import (
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb/service"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
- "github.com/anyproto/anytype-heart/pkg/lib/pb/model"
)
var (
ErrFailedGetObjectsInList = errors.New("failed to get objects in list")
ErrFailedAddObjectsToList = errors.New("failed to add objects to list")
ErrFailedRemoveObjectsFromList = errors.New("failed to remove objects from list")
- ErrFailedUpdateObjectsInList = errors.New("failed to update objects in list")
)
type Service interface {
- GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]*model.Object, int, bool, error)
+ GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]object.Object, int, bool, error)
AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIds []string) error
RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIds []string) error
- UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIds []string) error
}
type ListService struct {
@@ -92,24 +89,3 @@ func (s *ListService) RemoveObjectsFromList(ctx context.Context, spaceId string,
return nil
}
-
-// UpdateObjectsInList updates an object in a list
-func (s *ListService) UpdateObjectsInList(ctx context.Context, spaceId string, listId string, objectIds []string) error {
- resp := s.mw.BlockDataviewObjectOrderUpdate(ctx, &pb.RpcBlockDataviewObjectOrderUpdateRequest{
- ContextId: listId,
- BlockId: "dataview",
- ObjectOrders: []*model.BlockContentDataviewObjectOrder{
- {
- ViewId: "", // TODO: handle viewId
- GroupId: "",
- ObjectIds: objectIds,
- },
- },
- })
-
- if resp.Error.Code != pb.RpcBlockDataviewObjectOrderUpdateResponseError_NULL {
- return ErrFailedUpdateObjectsInList
- }
-
- return nil
-}
diff --git a/core/api/server/router.go b/core/api/server/router.go
index 23d094bbb7..6bc0174119 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -71,7 +71,6 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
v1.GET("/spaces/:space_id/lists/:list_id/objects", list.GetObjectsInListHandler(s.listService))
v1.POST("/spaces/:space_id/lists/:list_id/objects", list.AddObjectsToListHandler(s.listService))
v1.DELETE("/spaces/:space_id/lists/:list_id/objects", list.RemoveObjectsFromListHandler(s.listService))
- v1.PATCH("/spaces/:space_id/lists/:list_id/objects", list.UpdateObjectsInListHandler(s.listService))
// Object
v1.GET("/spaces/:space_id/objects", object.GetObjectsHandler(s.objectService))
From cd836a670f17f8979fb7c5af586c6e1a86ae38b2 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 14 Feb 2025 16:29:28 +0100
Subject: [PATCH 14/31] GO-4459: Return 404 for deleted object
---
core/api/internal/object/service.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 284a588ad3..3a51a343f4 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -117,7 +117,7 @@ func (s *ObjectService) GetObject(ctx context.Context, spaceId string, objectId
ObjectId: objectId,
})
- if resp.Error.Code == pb.RpcObjectShowResponseError_NOT_FOUND {
+ if resp.Error.Code == pb.RpcObjectShowResponseError_NOT_FOUND || resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIsArchived.String()].GetBoolValue() {
return Object{}, ErrObjectNotFound
}
From 40349517bc7a23b3134dd9b7deac48378d707dbe Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 14 Feb 2025 17:21:47 +0100
Subject: [PATCH 15/31] GO-4459: Refactor data models to include 'object'
property and return entire type for object
---
core/api/docs/docs.go | 46 ++++----
core/api/docs/swagger.json | 46 ++++----
core/api/docs/swagger.yaml | 36 ++++---
core/api/internal/object/model.go | 13 +--
core/api/internal/object/service.go | 25 ++---
core/api/internal/object/service_test.go | 129 +++++++++++++----------
core/api/internal/search/service_test.go | 72 ++++++-------
core/api/internal/space/model.go | 4 +-
core/api/internal/space/service.go | 6 +-
core/api/util/util.go | 34 ------
10 files changed, 203 insertions(+), 208 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index bc7016d05f..0c3db26bad 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -1517,6 +1517,11 @@ const docTemplate = `{
"type": "string",
"example": "My object"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "object"
+ },
"root_id": {
"description": "The id of the object's root",
"type": "string",
@@ -1534,8 +1539,11 @@ const docTemplate = `{
},
"type": {
"description": "The type of the object",
- "type": "string",
- "example": "Page"
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Type"
+ }
+ ]
}
}
},
@@ -1570,8 +1578,8 @@ const docTemplate = `{
"type": "string",
"example": "My template"
},
- "type": {
- "description": "The type of the object",
+ "object": {
+ "description": "The data model of the object",
"type": "string",
"example": "template"
}
@@ -1654,16 +1662,16 @@ const docTemplate = `{
"type": "string",
"example": "Page"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "type"
+ },
"recommended_layout": {
"description": "The recommended layout of the type",
"type": "string",
"example": "todo"
},
- "type": {
- "description": "The type of the object",
- "type": "string",
- "example": "type"
- },
"unique_key": {
"description": "The unique key of the type",
"type": "string",
@@ -1902,6 +1910,11 @@ const docTemplate = `{
"type": "string",
"example": "John Doe"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "member"
+ },
"role": {
"description": "The role of the member",
"type": "string",
@@ -1912,11 +1925,6 @@ const docTemplate = `{
"NoPermission"
],
"example": "Owner"
- },
- "type": {
- "description": "The type of the object",
- "type": "string",
- "example": "member"
}
}
},
@@ -1996,6 +2004,11 @@ const docTemplate = `{
"type": "string",
"example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "space"
+ },
"profile_object_id": {
"description": "The id of the profile object",
"type": "string",
@@ -2016,11 +2029,6 @@ const docTemplate = `{
"type": "string",
"example": ""
},
- "type": {
- "description": "The type of the object",
- "type": "string",
- "example": "space"
- },
"widgets_id": {
"description": "The id of the widgets",
"type": "string",
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index d8ba3d1463..223b833839 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -1511,6 +1511,11 @@
"type": "string",
"example": "My object"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "object"
+ },
"root_id": {
"description": "The id of the object's root",
"type": "string",
@@ -1528,8 +1533,11 @@
},
"type": {
"description": "The type of the object",
- "type": "string",
- "example": "Page"
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Type"
+ }
+ ]
}
}
},
@@ -1564,8 +1572,8 @@
"type": "string",
"example": "My template"
},
- "type": {
- "description": "The type of the object",
+ "object": {
+ "description": "The data model of the object",
"type": "string",
"example": "template"
}
@@ -1648,16 +1656,16 @@
"type": "string",
"example": "Page"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "type"
+ },
"recommended_layout": {
"description": "The recommended layout of the type",
"type": "string",
"example": "todo"
},
- "type": {
- "description": "The type of the object",
- "type": "string",
- "example": "type"
- },
"unique_key": {
"description": "The unique key of the type",
"type": "string",
@@ -1896,6 +1904,11 @@
"type": "string",
"example": "John Doe"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "member"
+ },
"role": {
"description": "The role of the member",
"type": "string",
@@ -1906,11 +1919,6 @@
"NoPermission"
],
"example": "Owner"
- },
- "type": {
- "description": "The type of the object",
- "type": "string",
- "example": "member"
}
}
},
@@ -1990,6 +1998,11 @@
"type": "string",
"example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
},
+ "object": {
+ "description": "The data model of the object",
+ "type": "string",
+ "example": "space"
+ },
"profile_object_id": {
"description": "The id of the profile object",
"type": "string",
@@ -2010,11 +2023,6 @@
"type": "string",
"example": ""
},
- "type": {
- "description": "The type of the object",
- "type": "string",
- "example": "space"
- },
"widgets_id": {
"description": "The id of the widgets",
"type": "string",
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 46c1110f70..0dd2b302ac 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -176,6 +176,10 @@ definitions:
description: The name of the object
example: My object
type: string
+ object:
+ description: The data model of the object
+ example: object
+ type: string
root_id:
description: The id of the object's root
example: bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u
@@ -190,9 +194,9 @@ definitions:
example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
type: string
type:
+ allOf:
+ - $ref: '#/definitions/object.Type'
description: The type of the object
- example: Page
- type: string
type: object
object.ObjectResponse:
properties:
@@ -215,8 +219,8 @@ definitions:
description: The name of the template
example: My template
type: string
- type:
- description: The type of the object
+ object:
+ description: The data model of the object
example: template
type: string
type: object
@@ -279,14 +283,14 @@ definitions:
description: The name of the type
example: Page
type: string
+ object:
+ description: The data model of the object
+ example: type
+ type: string
recommended_layout:
description: The recommended layout of the type
example: todo
type: string
- type:
- description: The type of the object
- example: type
- type: string
unique_key:
description: The unique key of the type
example: ot-page
@@ -449,6 +453,10 @@ definitions:
description: The name of the member
example: John Doe
type: string
+ object:
+ description: The data model of the object
+ example: member
+ type: string
role:
description: The role of the member
enum:
@@ -458,10 +466,6 @@ definitions:
- NoPermission
example: Owner
type: string
- type:
- description: The type of the object
- example: member
- type: string
type: object
space.MemberResponse:
properties:
@@ -520,6 +524,10 @@ definitions:
description: The network id of the space
example: N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU
type: string
+ object:
+ description: The data model of the object
+ example: space
+ type: string
profile_object_id:
description: The id of the profile object
example: bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4
@@ -537,10 +545,6 @@ definitions:
description: The timezone of the account
example: ""
type: string
- type:
- description: The type of the object
- example: space
- type: string
widgets_id:
description: The id of the widgets
example: bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva
diff --git a/core/api/internal/object/model.go b/core/api/internal/object/model.go
index d591214913..5846100ae0 100644
--- a/core/api/internal/object/model.go
+++ b/core/api/internal/object/model.go
@@ -15,10 +15,11 @@ type ObjectResponse struct {
}
type Object struct {
- Type string `json:"type" example:"Page"` // The type of the object
+ Object string `json:"object" example:"object"` // The data model of the object
Id string `json:"id" example:"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"` // The id of the object
Name string `json:"name" example:"My object"` // The name of the object
Icon string `json:"icon" example:"📄"` // The icon of the object
+ Type Type `json:"type"` // The type of the object
Snippet string `json:"snippet" example:"The beginning of the object body..."` // The snippet of the object, especially important for notes as they don't have a name
Layout string `json:"layout" example:"basic"` // The layout of the object
SpaceId string `json:"space_id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"` // The id of the space the object is in
@@ -73,7 +74,7 @@ type TypeResponse struct {
}
type Type struct {
- Type string `json:"type" example:"type"` // The type of the object
+ Object string `json:"object" example:"type"` // The data model of the object
Id string `json:"id" example:"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"` // The id of the type
UniqueKey string `json:"unique_key" example:"ot-page"` // The unique key of the type
Name string `json:"name" example:"Page"` // The name of the type
@@ -86,8 +87,8 @@ type TemplateResponse struct {
}
type Template struct {
- Type string `json:"type" example:"template"` // The type of the object
- Id string `json:"id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"` // The id of the template
- Name string `json:"name" example:"My template"` // The name of the template
- Icon string `json:"icon" example:"📄"` // The icon of the template
+ Object string `json:"object" example:"template"` // The data model of the object
+ Id string `json:"id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"` // The id of the template
+ Name string `json:"name" example:"My template"` // The name of the template
+ Icon string `json:"icon" example:"📄"` // The icon of the template
}
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 3a51a343f4..d979245d16 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -126,16 +126,17 @@ func (s *ObjectService) GetObject(ctx context.Context, spaceId string, objectId
}
icon := util.GetIconFromEmojiOrImage(s.AccountInfo, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
- objectTypeName, err := util.ResolveTypeToName(s.mw, spaceId, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyType.String()].GetStringValue())
+ objectType, err := s.GetType(ctx, spaceId, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyType.String()].GetStringValue())
if err != nil {
return Object{}, err
}
object := Object{
- Type: objectTypeName,
+ Object: "object",
Id: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyId.String()].GetStringValue(),
Name: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
Icon: icon,
+ Type: objectType,
Snippet: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySnippet.String()].GetStringValue(),
Layout: model.ObjectTypeLayout_name[int32(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLayout.String()].GetNumberValue())],
SpaceId: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(),
@@ -299,7 +300,7 @@ func (s *ObjectService) ListTypes(ctx context.Context, spaceId string, offset in
for _, record := range paginatedTypes {
types = append(types, Type{
- Type: "type",
+ Object: "type",
Id: record.Fields[bundle.RelationKeyId.String()].GetStringValue(),
UniqueKey: record.Fields[bundle.RelationKeyUniqueKey.String()].GetStringValue(),
Name: record.Fields[bundle.RelationKeyName.String()].GetStringValue(),
@@ -326,7 +327,7 @@ func (s *ObjectService) GetType(ctx context.Context, spaceId string, typeId stri
}
return Type{
- Type: "type",
+ Object: "type",
Id: typeId,
UniqueKey: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyUniqueKey.String()].GetStringValue(),
Name: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
@@ -399,10 +400,10 @@ func (s *ObjectService) ListTemplates(ctx context.Context, spaceId string, typeI
}
templates = append(templates, Template{
- Type: "template",
- Id: templateId,
- Name: templateResp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
- Icon: templateResp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(),
+ Object: "template",
+ Id: templateId,
+ Name: templateResp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
+ Icon: templateResp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(),
})
}
@@ -425,10 +426,10 @@ func (s *ObjectService) GetTemplate(ctx context.Context, spaceId string, typeId
}
return Template{
- Type: "template",
- Id: templateId,
- Name: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
- Icon: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(),
+ Object: "template",
+ Id: templateId,
+ Name: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
+ Icon: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(),
}, nil
}
diff --git a/core/api/internal/object/service_test.go b/core/api/internal/object/service_test.go
index 5ae1f6ba25..f865b96ea7 100644
--- a/core/api/internal/object/service_test.go
+++ b/core/api/internal/object/service_test.go
@@ -23,7 +23,6 @@ const (
gatewayUrl = "http://localhost:31006"
mockedSpaceId = "mocked-space-id"
mockedObjectId = "mocked-object-id"
- mockedObjectType = "mocked-object-type"
mockedNewObjectId = "mocked-new-object-id"
mockedObjectName = "mocked-object-name"
mockedObjectSnippet = "mocked-object-snippet"
@@ -99,7 +98,7 @@ func TestObjectService_ListObjects(t *testing.T) {
bundle.RelationKeyName.String(): pbtypes.String(mockedObjectName),
bundle.RelationKeySnippet.String(): pbtypes.String(mockedObjectSnippet),
bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedObjectIcon),
- bundle.RelationKeyType.String(): pbtypes.String(mockedObjectTypeUniqueKey),
+ bundle.RelationKeyType.String(): pbtypes.String(mockedTypeId),
bundle.RelationKeyLayout.String(): pbtypes.Float64(float64(model.ObjectType_basic)),
},
},
@@ -122,7 +121,7 @@ func TestObjectService_ListObjects(t *testing.T) {
bundle.RelationKeyName.String(): pbtypes.String(mockedObjectName),
bundle.RelationKeySnippet.String(): pbtypes.String(mockedObjectSnippet),
bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedObjectIcon),
- bundle.RelationKeyType.String(): pbtypes.String(mockedObjectTypeUniqueKey),
+ bundle.RelationKeyType.String(): pbtypes.String(mockedTypeId),
bundle.RelationKeyCreatedDate.String(): pbtypes.Float64(888888),
bundle.RelationKeyLastModifiedDate.String(): pbtypes.Float64(999999),
bundle.RelationKeyLastOpenedDate.String(): pbtypes.Float64(0),
@@ -136,25 +135,26 @@ func TestObjectService_ListObjects(t *testing.T) {
}).Once()
// Mock type resolution
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- RelationKey: bundle.RelationKeyUniqueKey.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(mockedObjectTypeUniqueKey),
- },
- },
- Keys: []string{bundle.RelationKeyName.String()},
- }).Return(&pb.RpcObjectSearchResponse{
- Records: []*types.Struct{
- {
- Fields: map[string]*types.Value{
- bundle.RelationKeyName.String(): pbtypes.String(mockedObjectType),
+ fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
+ SpaceId: mockedSpaceId,
+ ObjectId: mockedTypeId,
+ }).Return(&pb.RpcObjectShowResponse{
+ ObjectView: &model.ObjectView{
+ RootId: mockedTypeId,
+ Details: []*model.ObjectViewDetailsSet{
+ {
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
+ bundle.RelationKeyName.String(): pbtypes.String(mockedTypeName),
+ bundle.RelationKeyUniqueKey.String(): pbtypes.String(mockedTypeUniqueKey),
+ bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedTypeIcon),
+ },
+ },
},
},
},
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}).Once()
// Mock participant details
@@ -190,7 +190,10 @@ func TestObjectService_ListObjects(t *testing.T) {
// then
require.NoError(t, err)
require.Len(t, objects, 1)
- require.Equal(t, mockedObjectType, objects[0].Type)
+ require.Equal(t, mockedTypeId, objects[0].Type.Id)
+ require.Equal(t, mockedTypeName, objects[0].Type.Name)
+ require.Equal(t, mockedTypeUniqueKey, objects[0].Type.UniqueKey)
+ require.Equal(t, mockedTypeIcon, objects[0].Type.Icon)
require.Equal(t, mockedObjectId, objects[0].Id)
require.Equal(t, mockedObjectName, objects[0].Name)
require.Equal(t, mockedObjectSnippet, objects[0].Snippet)
@@ -263,7 +266,7 @@ func TestObjectService_GetObject(t *testing.T) {
bundle.RelationKeyName.String(): pbtypes.String(mockedObjectName),
bundle.RelationKeySnippet.String(): pbtypes.String(mockedObjectSnippet),
bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedObjectName),
- bundle.RelationKeyType.String(): pbtypes.String(mockedObjectTypeUniqueKey),
+ bundle.RelationKeyType.String(): pbtypes.String(mockedTypeId),
bundle.RelationKeyLastModifiedDate.String(): pbtypes.Float64(999999),
bundle.RelationKeyCreatedDate.String(): pbtypes.Float64(888888),
bundle.RelationKeyLastOpenedDate.String(): pbtypes.Float64(0),
@@ -276,26 +279,27 @@ func TestObjectService_GetObject(t *testing.T) {
}, nil).Once()
// Mock type resolution
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- RelationKey: bundle.RelationKeyUniqueKey.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(mockedObjectTypeUniqueKey),
- },
- },
- Keys: []string{bundle.RelationKeyName.String()},
- }).Return(&pb.RpcObjectSearchResponse{
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
- Records: []*types.Struct{
- {
- Fields: map[string]*types.Value{
- bundle.RelationKeyName.String(): pbtypes.String(mockedObjectType),
+ fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
+ SpaceId: mockedSpaceId,
+ ObjectId: mockedTypeId,
+ }).Return(&pb.RpcObjectShowResponse{
+ ObjectView: &model.ObjectView{
+ RootId: mockedTypeId,
+ Details: []*model.ObjectViewDetailsSet{
+ {
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
+ bundle.RelationKeyName.String(): pbtypes.String(mockedTypeName),
+ bundle.RelationKeyUniqueKey.String(): pbtypes.String(mockedTypeUniqueKey),
+ bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedTypeIcon),
+ },
+ },
},
},
},
- }, nil).Once()
+ Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
+ }).Once()
// Mock participant details
fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
@@ -329,7 +333,11 @@ func TestObjectService_GetObject(t *testing.T) {
// then
require.NoError(t, err)
- require.Equal(t, mockedObjectType, object.Type)
+ require.Equal(t, "object", object.Object)
+ require.Equal(t, mockedTypeId, object.Type.Id)
+ require.Equal(t, mockedTypeName, object.Type.Name)
+ require.Equal(t, mockedTypeUniqueKey, object.Type.UniqueKey)
+ require.Equal(t, mockedTypeIcon, object.Type.Icon)
require.Equal(t, mockedObjectId, object.Id)
require.Equal(t, mockedObjectName, object.Name)
require.Equal(t, mockedObjectSnippet, object.Snippet)
@@ -421,7 +429,7 @@ func TestObjectService_CreateObject(t *testing.T) {
bundle.RelationKeyId.String(): pbtypes.String(mockedNewObjectId),
bundle.RelationKeyName.String(): pbtypes.String(mockedObjectName),
bundle.RelationKeyLayout.String(): pbtypes.Float64(float64(model.ObjectType_basic)),
- bundle.RelationKeyType.String(): pbtypes.String(mockedObjectTypeUniqueKey),
+ bundle.RelationKeyType.String(): pbtypes.String(mockedTypeId),
bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedObjectIcon),
bundle.RelationKeySpaceId.String(): pbtypes.String(mockedSpaceId),
},
@@ -433,25 +441,26 @@ func TestObjectService_CreateObject(t *testing.T) {
}).Once()
// Mock type resolution
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- RelationKey: bundle.RelationKeyUniqueKey.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(mockedObjectTypeUniqueKey),
- },
- },
- Keys: []string{bundle.RelationKeyName.String()},
- }).Return(&pb.RpcObjectSearchResponse{
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
- Records: []*types.Struct{
- {
- Fields: map[string]*types.Value{
- bundle.RelationKeyName.String(): pbtypes.String(mockedObjectType),
+ fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
+ SpaceId: mockedSpaceId,
+ ObjectId: mockedTypeId,
+ }).Return(&pb.RpcObjectShowResponse{
+ ObjectView: &model.ObjectView{
+ RootId: mockedTypeId,
+ Details: []*model.ObjectViewDetailsSet{
+ {
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
+ bundle.RelationKeyName.String(): pbtypes.String(mockedTypeName),
+ bundle.RelationKeyUniqueKey.String(): pbtypes.String(mockedTypeUniqueKey),
+ bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedTypeIcon),
+ },
+ },
},
},
},
+ Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}).Once()
// Mock participant details
@@ -491,7 +500,11 @@ func TestObjectService_CreateObject(t *testing.T) {
// then
require.NoError(t, err)
- require.Equal(t, mockedObjectType, object.Type)
+ require.Equal(t, "object", object.Object)
+ require.Equal(t, mockedTypeId, object.Type.Id)
+ require.Equal(t, mockedTypeName, object.Type.Name)
+ require.Equal(t, mockedTypeUniqueKey, object.Type.UniqueKey)
+ require.Equal(t, mockedTypeIcon, object.Type.Icon)
require.Equal(t, mockedNewObjectId, object.Id)
require.Equal(t, mockedObjectName, object.Name)
require.Equal(t, mockedObjectIcon, object.Icon)
@@ -749,7 +762,7 @@ func TestObjectService_GetTemplate(t *testing.T) {
}).Once()
// when
- template, err := fx.GetTemplate(ctx, mockedSpaceId, mockedObjectType, mockedTemplateId)
+ template, err := fx.GetTemplate(ctx, mockedSpaceId, mockedTypeId, mockedTemplateId)
// then
require.NoError(t, err)
diff --git a/core/api/internal/search/service_test.go b/core/api/internal/search/service_test.go
index 1f248690f3..49e4567abb 100644
--- a/core/api/internal/search/service_test.go
+++ b/core/api/internal/search/service_test.go
@@ -35,7 +35,6 @@ const (
mockedTagId2 = "mocked-tag-id-2"
mockedTagValue2 = "mocked-tag-value-2"
mockedTagColor2 = "mocked-tag-color-2"
- mockedObjectTypeName = "mocked-object-type-name"
mockedParticipantName = "mocked-participant-name"
mockedParticipantIcon = "mocked-participant-icon"
mockedParticipantImage = "mocked-participant-image"
@@ -282,26 +281,23 @@ func TestSearchService_GlobalSearch(t *testing.T) {
}, nil).Once()
// Mock type resolution
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- Operator: model.BlockContentDataviewFilter_No,
- RelationKey: bundle.RelationKeyId.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(mockedType),
- },
- },
- Keys: []string{bundle.RelationKeyName.String()},
- }).Return(&pb.RpcObjectSearchResponse{
- Records: []*types.Struct{
- {
- Fields: map[string]*types.Value{
- bundle.RelationKeyName.String(): pbtypes.String(mockedObjectTypeName),
+ fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
+ SpaceId: mockedSpaceId,
+ ObjectId: mockedType,
+ }).Return(&pb.RpcObjectShowResponse{
+ ObjectView: &model.ObjectView{
+ RootId: mockedType,
+ Details: []*model.ObjectViewDetailsSet{
+ {
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedType),
+ },
+ },
},
},
},
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}).Once()
// Mock participant details
@@ -346,10 +342,10 @@ func TestSearchService_GlobalSearch(t *testing.T) {
// then
require.NoError(t, err)
require.Len(t, objects, 1)
- require.Equal(t, mockedObjectTypeName, objects[0].Type)
- require.Equal(t, mockedSpaceId, objects[0].SpaceId)
- require.Equal(t, mockedObjectName, objects[0].Name)
require.Equal(t, mockedObjectId, objects[0].Id)
+ require.Equal(t, mockedObjectName, objects[0].Name)
+ require.Equal(t, mockedType, objects[0].Type.Id)
+ require.Equal(t, mockedSpaceId, objects[0].SpaceId)
require.Equal(t, model.ObjectTypeLayout_name[int32(model.ObjectType_basic)], objects[0].Layout)
require.Equal(t, "🌐", objects[0].Icon)
require.Equal(t, "This is a sample text block", objects[0].Blocks[2].Text.Text)
@@ -494,26 +490,23 @@ func TestSearchService_Search(t *testing.T) {
}).Once()
// Mock type resolution
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- Operator: model.BlockContentDataviewFilter_No,
- RelationKey: bundle.RelationKeyId.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(mockedType),
- },
- },
- Keys: []string{bundle.RelationKeyName.String()},
- }).Return(&pb.RpcObjectSearchResponse{
- Records: []*types.Struct{
- {
- Fields: map[string]*types.Value{
- bundle.RelationKeyName.String(): pbtypes.String(mockedObjectTypeName),
+ fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
+ SpaceId: mockedSpaceId,
+ ObjectId: mockedType,
+ }).Return(&pb.RpcObjectShowResponse{
+ ObjectView: &model.ObjectView{
+ RootId: mockedType,
+ Details: []*model.ObjectViewDetailsSet{
+ {
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedType),
+ },
+ },
},
},
},
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}).Once()
// Mock participant details
@@ -546,8 +539,9 @@ func TestSearchService_Search(t *testing.T) {
// then
require.NoError(t, err)
require.Len(t, objects, 1)
- require.Equal(t, mockedObjectName, objects[0].Name)
require.Equal(t, mockedObjectId, objects[0].Id)
+ require.Equal(t, mockedObjectName, objects[0].Name)
+ require.Equal(t, mockedType, objects[0].Type.Id)
require.Equal(t, mockedSpaceId, objects[0].SpaceId)
require.Equal(t, model.ObjectTypeLayout_name[int32(model.ObjectType_basic)], objects[0].Layout)
diff --git a/core/api/internal/space/model.go b/core/api/internal/space/model.go
index 6805de3ccb..16ebe1fb5b 100644
--- a/core/api/internal/space/model.go
+++ b/core/api/internal/space/model.go
@@ -9,7 +9,7 @@ type CreateSpaceRequest struct {
}
type Space struct {
- Type string `json:"type" example:"space"` // The type of the object
+ Object string `json:"object" example:"space"` // The data model of the object
Id string `json:"id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"` // The id of the space
Name string `json:"name" example:"My Space"` // The name of the space
Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"` // The icon of the space
@@ -35,7 +35,7 @@ type MemberResponse struct {
}
type Member struct {
- Type string `json:"type" example:"member"` // The type of the object
+ Object string `json:"object" example:"member"` // The data model of the object
Id string `json:"id" example:"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"` // The profile object id of the member
Name string `json:"name" example:"John Doe"` // The name of the member
Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"` // The icon of the member
diff --git a/core/api/internal/space/service.go b/core/api/internal/space/service.go
index eb83f636c7..1b36244e0b 100644
--- a/core/api/internal/space/service.go
+++ b/core/api/internal/space/service.go
@@ -198,7 +198,7 @@ func (s *SpaceService) ListMembers(ctx context.Context, spaceId string, offset i
icon := util.GetIconFromEmojiOrImage(s.AccountInfo, record.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), record.Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
member := Member{
- Type: "member",
+ Object: "member",
Id: record.Fields[bundle.RelationKeyId.String()].GetStringValue(),
Name: record.Fields[bundle.RelationKeyName.String()].GetStringValue(),
Icon: icon,
@@ -239,7 +239,7 @@ func (s *SpaceService) GetMember(ctx context.Context, spaceId string, memberId s
icon := util.GetIconFromEmojiOrImage(s.AccountInfo, "", resp.Records[0].Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
return Member{
- Type: "member",
+ Object: "member",
Id: resp.Records[0].Fields[bundle.RelationKeyId.String()].GetStringValue(),
Name: resp.Records[0].Fields[bundle.RelationKeyName.String()].GetStringValue(),
Icon: icon,
@@ -261,7 +261,7 @@ func (s *SpaceService) getWorkspaceInfo(spaceId string, name string, icon string
}
return Space{
- Type: "space",
+ Object: "space",
Id: spaceId,
Name: name,
Icon: icon,
diff --git a/core/api/util/util.go b/core/api/util/util.go
index 6c5a74eb98..c8ce71dec2 100644
--- a/core/api/util/util.go
+++ b/core/api/util/util.go
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
- "strings"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb/service"
@@ -31,39 +30,6 @@ func GetIconFromEmojiOrImage(accountInfo *model.AccountInfo, iconEmoji string, i
return ""
}
-// ResolveTypeToName resolves the type ID to the name of the type, e.g. "ot-page" to "Page" or "bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu" to "Custom Type"
-func ResolveTypeToName(mw service.ClientCommandsServer, spaceId string, typeId string) (typeName string, err error) {
- // Can't look up preinstalled types based on relation key, therefore need to use unique key
- relKey := bundle.RelationKeyId.String()
- if strings.HasPrefix(typeId, "ot-") {
- relKey = bundle.RelationKeyUniqueKey.String()
- }
-
- // Call ObjectSearch for object of specified type and return the name
- resp := mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
- SpaceId: spaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- Operator: model.BlockContentDataviewFilter_No,
- RelationKey: relKey,
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(typeId),
- },
- },
- Keys: []string{bundle.RelationKeyName.String()},
- })
-
- if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
- return "", ErrFailedSearchType
- }
-
- if len(resp.Records) == 0 {
- return "", ErrorTypeNotFound
- }
-
- return resp.Records[0].Fields[bundle.RelationKeyName.String()].GetStringValue(), nil
-}
-
func ResolveUniqueKeyToTypeId(mw service.ClientCommandsServer, spaceId string, uniqueKey string) (typeId string, err error) {
// Call ObjectSearch for type with unique key and return the type's ID
resp := mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
From 81cdd2ee884709e0c856cc1d70da1a2488b29d5d Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 14 Feb 2025 18:44:25 +0100
Subject: [PATCH 16/31] GO-4459: Add relation format to detail entries
---
core/api/internal/object/service.go | 29 ++++++++++++++++++++----
core/api/internal/object/service_test.go | 12 +++++-----
core/api/internal/search/service_test.go | 6 ++---
3 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index d979245d16..ab077f4790 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -435,6 +435,7 @@ func (s *ObjectService) GetTemplate(ctx context.Context, spaceId string, typeId
// GetDetails returns the list of details from the ObjectShowResponse.
func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
+ relationFormatMap := s.getRelationFormatMap(resp.ObjectView.RelationLinks)
creator := resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyCreator.String()].GetStringValue()
lastModifiedBy := resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastModifiedBy.String()].GetStringValue()
@@ -462,42 +463,62 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
{
Id: "last_modified_date",
Details: map[string]interface{}{
- "last_modified_date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastModifiedDate.String()].GetNumberValue()),
+ "type": relationFormatMap[bundle.RelationKeyLastModifiedDate.String()],
+ "date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastModifiedDate.String()].GetNumberValue()),
},
},
{
Id: "last_modified_by",
Details: map[string]interface{}{
+ "type": relationFormatMap[bundle.RelationKeyLastModifiedBy.String()],
"details": memberLastModifiedBy,
},
},
{
Id: "created_date",
Details: map[string]interface{}{
- "created_date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyCreatedDate.String()].GetNumberValue()),
+ "type": relationFormatMap[bundle.RelationKeyCreatedDate.String()],
+ "date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyCreatedDate.String()].GetNumberValue()),
},
},
{
Id: "created_by",
Details: map[string]interface{}{
+ "type": relationFormatMap[bundle.RelationKeyCreator.String()],
"details": memberCreator,
},
},
{
Id: "last_opened_date",
Details: map[string]interface{}{
- "last_opened_date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastOpenedDate.String()].GetNumberValue()),
+ "type": relationFormatMap[bundle.RelationKeyLastOpenedDate.String()],
+ "date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastOpenedDate.String()].GetNumberValue()),
},
},
{
Id: "tags",
Details: map[string]interface{}{
- "tags": s.getTags(resp),
+ "type": relationFormatMap[bundle.RelationKeyTag.String()],
+ "multi_select": s.getTags(resp),
},
},
}
}
+// getRelationFormatMapFromResponse returns the map of relation key to relation format from the ObjectShowResponse.
+func (s *ObjectService) getRelationFormatMap(relationLinks []*model.RelationLink) map[string]string {
+ var relationFormatToName = model.RelationFormat_name
+ relationFormatToName[int32(model.RelationFormat_tag)] = "multi_select"
+ relationFormatToName[int32(model.RelationFormat_status)] = "select"
+
+ relationFormatMap := map[string]string{}
+ for _, detail := range relationLinks {
+ relationFormatMap[detail.Key] = relationFormatToName[int32(detail.Format)]
+ }
+
+ return relationFormatMap
+}
+
// getTags returns the list of tags from the ObjectShowResponse
func (s *ObjectService) getTags(resp *pb.RpcObjectShowResponse) []Tag {
tags := []Tag{}
diff --git a/core/api/internal/object/service_test.go b/core/api/internal/object/service_test.go
index f865b96ea7..976b2f1ef0 100644
--- a/core/api/internal/object/service_test.go
+++ b/core/api/internal/object/service_test.go
@@ -202,15 +202,15 @@ func TestObjectService_ListObjects(t *testing.T) {
for _, detail := range objects[0].Details {
if detail.Id == "created_date" {
- require.Equal(t, "1970-01-11T06:54:48Z", detail.Details["created_date"])
+ require.Equal(t, "1970-01-11T06:54:48Z", detail.Details["date"])
} else if detail.Id == "created_by" {
require.Empty(t, detail.Details["created_by"])
} else if detail.Id == "last_modified_date" {
- require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["last_modified_date"])
+ require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["date"])
} else if detail.Id == "last_modified_by" {
require.Empty(t, detail.Details["last_modified_by"])
} else if detail.Id == "last_opened_date" {
- require.Equal(t, "1970-01-01T00:00:00Z", detail.Details["last_opened_date"])
+ require.Equal(t, "1970-01-01T00:00:00Z", detail.Details["date"])
} else if detail.Id == "tags" {
require.Empty(t, detail.Details["tags"])
} else {
@@ -346,15 +346,15 @@ func TestObjectService_GetObject(t *testing.T) {
for _, detail := range object.Details {
if detail.Id == "created_date" {
- require.Equal(t, "1970-01-11T06:54:48Z", detail.Details["created_date"])
+ require.Equal(t, "1970-01-11T06:54:48Z", detail.Details["date"])
} else if detail.Id == "created_by" {
require.Empty(t, detail.Details["created_by"])
} else if detail.Id == "last_modified_date" {
- require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["last_modified_date"])
+ require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["date"])
} else if detail.Id == "last_modified_by" {
require.Empty(t, detail.Details["last_modified_by"])
} else if detail.Id == "last_opened_date" {
- require.Equal(t, "1970-01-01T00:00:00Z", detail.Details["last_opened_date"])
+ require.Equal(t, "1970-01-01T00:00:00Z", detail.Details["date"])
} else if detail.Id == "tags" {
require.Empty(t, detail.Details["tags"])
} else {
diff --git a/core/api/internal/search/service_test.go b/core/api/internal/search/service_test.go
index 49e4567abb..8a55a0b9b6 100644
--- a/core/api/internal/search/service_test.go
+++ b/core/api/internal/search/service_test.go
@@ -353,9 +353,9 @@ func TestSearchService_GlobalSearch(t *testing.T) {
// check details
for _, detail := range objects[0].Details {
if detail.Id == "created_date" {
- require.Equal(t, "1970-01-11T06:54:48Z", detail.Details["created_date"])
+ require.Equal(t, "1970-01-11T06:54:48Z", detail.Details["date"])
} else if detail.Id == "last_modified_date" {
- require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["last_modified_date"])
+ require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["date"])
} else if detail.Id == "created_by" {
require.Equal(t, mockedParticipantId, detail.Details["details"].(space.Member).Id)
require.Equal(t, mockedParticipantName, detail.Details["details"].(space.Member).Name)
@@ -370,7 +370,7 @@ func TestSearchService_GlobalSearch(t *testing.T) {
// check tags
tags := []object.Tag{}
for _, detail := range objects[0].Details {
- if tagList, ok := detail.Details["tags"].([]object.Tag); ok {
+ if tagList, ok := detail.Details["multi_select"].([]object.Tag); ok {
for _, tag := range tagList {
tags = append(tags, tag)
}
From 039739fce727f24df17056f8bd747db61eb390d6 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 14 Feb 2025 19:32:19 +0100
Subject: [PATCH 17/31] GO-4459: Get type directly from details in GetObject
and fix detail key for object relation value
---
core/api/internal/object/service.go | 55 +++++++++++++++------
core/api/internal/object/service_test.go | 63 ++++++------------------
core/api/internal/search/service_test.go | 43 ++++------------
3 files changed, 65 insertions(+), 96 deletions(-)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index ab077f4790..10b074bd57 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -3,6 +3,7 @@ package object
import (
"context"
"errors"
+ "sync"
"time"
"github.com/gogo/protobuf/types"
@@ -126,23 +127,19 @@ func (s *ObjectService) GetObject(ctx context.Context, spaceId string, objectId
}
icon := util.GetIconFromEmojiOrImage(s.AccountInfo, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
- objectType, err := s.GetType(ctx, spaceId, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyType.String()].GetStringValue())
- if err != nil {
- return Object{}, err
- }
object := Object{
Object: "object",
Id: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyId.String()].GetStringValue(),
Name: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
Icon: icon,
- Type: objectType,
+ Type: s.getTypeFromDetails(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyType.String()].GetStringValue(), resp.ObjectView.Details),
Snippet: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySnippet.String()].GetStringValue(),
Layout: model.ObjectTypeLayout_name[int32(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLayout.String()].GetNumberValue())],
SpaceId: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(),
RootId: resp.ObjectView.RootId,
- Blocks: s.GetBlocks(resp),
- Details: s.GetDetails(resp),
+ Blocks: s.getBlocks(resp),
+ Details: s.getDetails(resp),
}
return object, nil
@@ -433,8 +430,32 @@ func (s *ObjectService) GetTemplate(ctx context.Context, spaceId string, typeId
}, nil
}
-// GetDetails returns the list of details from the ObjectShowResponse.
-func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
+// getTypeFromDetails returns the type from the details of the ObjectShowResponse.
+func (s *ObjectService) getTypeFromDetails(typeId string, details []*model.ObjectViewDetailsSet) Type {
+ var objectTypeDetail *types.Struct
+ for _, detail := range details {
+ if detail.Id == typeId {
+ objectTypeDetail = detail.GetDetails()
+ break
+ }
+ }
+
+ if objectTypeDetail == nil {
+ return Type{}
+ }
+
+ return Type{
+ Object: "type",
+ Id: typeId,
+ UniqueKey: objectTypeDetail.Fields[bundle.RelationKeyUniqueKey.String()].GetStringValue(),
+ Name: objectTypeDetail.Fields[bundle.RelationKeyName.String()].GetStringValue(),
+ Icon: objectTypeDetail.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(),
+ RecommendedLayout: model.ObjectTypeLayout_name[int32(objectTypeDetail.Fields[bundle.RelationKeyRecommendedLayout.String()].GetNumberValue())],
+ }
+}
+
+// getDetails returns the list of details from the ObjectShowResponse.
+func (s *ObjectService) getDetails(resp *pb.RpcObjectShowResponse) []Detail {
relationFormatMap := s.getRelationFormatMap(resp.ObjectView.RelationLinks)
creator := resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyCreator.String()].GetStringValue()
lastModifiedBy := resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastModifiedBy.String()].GetStringValue()
@@ -470,8 +491,8 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
{
Id: "last_modified_by",
Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyLastModifiedBy.String()],
- "details": memberLastModifiedBy,
+ "type": relationFormatMap[bundle.RelationKeyLastModifiedBy.String()],
+ "object": memberLastModifiedBy,
},
},
{
@@ -484,8 +505,8 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
{
Id: "created_by",
Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyCreator.String()],
- "details": memberCreator,
+ "type": relationFormatMap[bundle.RelationKeyCreator.String()],
+ "object": memberCreator,
},
},
{
@@ -508,6 +529,9 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
// getRelationFormatMapFromResponse returns the map of relation key to relation format from the ObjectShowResponse.
func (s *ObjectService) getRelationFormatMap(relationLinks []*model.RelationLink) map[string]string {
var relationFormatToName = model.RelationFormat_name
+ var mu sync.Mutex
+
+ mu.Lock()
relationFormatToName[int32(model.RelationFormat_tag)] = "multi_select"
relationFormatToName[int32(model.RelationFormat_status)] = "select"
@@ -515,6 +539,7 @@ func (s *ObjectService) getRelationFormatMap(relationLinks []*model.RelationLink
for _, detail := range relationLinks {
relationFormatMap[detail.Key] = relationFormatToName[int32(detail.Format)]
}
+ mu.Unlock()
return relationFormatMap
}
@@ -544,8 +569,8 @@ func (s *ObjectService) getTags(resp *pb.RpcObjectShowResponse) []Tag {
return tags
}
-// GetBlocks returns the list of blocks from the ObjectShowResponse.
-func (s *ObjectService) GetBlocks(resp *pb.RpcObjectShowResponse) []Block {
+// getBlocks returns the list of blocks from the ObjectShowResponse.
+func (s *ObjectService) getBlocks(resp *pb.RpcObjectShowResponse) []Block {
blocks := []Block{}
for _, block := range resp.ObjectView.Blocks {
diff --git a/core/api/internal/object/service_test.go b/core/api/internal/object/service_test.go
index 976b2f1ef0..ed40c5b5ef 100644
--- a/core/api/internal/object/service_test.go
+++ b/core/api/internal/object/service_test.go
@@ -115,6 +115,7 @@ func TestObjectService_ListObjects(t *testing.T) {
RootId: mockedObjectId,
Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedObjectId,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedObjectId),
@@ -129,20 +130,8 @@ func TestObjectService_ListObjects(t *testing.T) {
},
},
},
- },
- },
- Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
- }).Once()
-
- // Mock type resolution
- fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
- SpaceId: mockedSpaceId,
- ObjectId: mockedTypeId,
- }).Return(&pb.RpcObjectShowResponse{
- ObjectView: &model.ObjectView{
- RootId: mockedTypeId,
- Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedTypeId,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
@@ -260,6 +249,7 @@ func TestObjectService_GetObject(t *testing.T) {
RootId: mockedObjectId,
Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedObjectId,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedObjectId),
@@ -274,32 +264,20 @@ func TestObjectService_GetObject(t *testing.T) {
},
},
},
- },
- },
- }, nil).Once()
-
- // Mock type resolution
- fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
- SpaceId: mockedSpaceId,
- ObjectId: mockedTypeId,
- }).Return(&pb.RpcObjectShowResponse{
- ObjectView: &model.ObjectView{
- RootId: mockedTypeId,
- Details: []*model.ObjectViewDetailsSet{
- {
- Details: &types.Struct{
- Fields: map[string]*types.Value{
- bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
- bundle.RelationKeyName.String(): pbtypes.String(mockedTypeName),
- bundle.RelationKeyUniqueKey.String(): pbtypes.String(mockedTypeUniqueKey),
- bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedTypeIcon),
+ {
+ Id: mockedTypeId,
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
+ bundle.RelationKeyName.String(): pbtypes.String(mockedTypeName),
+ bundle.RelationKeyUniqueKey.String(): pbtypes.String(mockedTypeUniqueKey),
+ bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedTypeIcon),
+ },
},
},
},
},
- },
- Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
- }).Once()
+ }, nil).Once()
// Mock participant details
fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
@@ -424,6 +402,7 @@ func TestObjectService_CreateObject(t *testing.T) {
RootId: mockedNewObjectId,
Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedNewObjectId,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedNewObjectId),
@@ -435,20 +414,8 @@ func TestObjectService_CreateObject(t *testing.T) {
},
},
},
- },
- },
- Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
- }).Once()
-
- // Mock type resolution
- fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
- SpaceId: mockedSpaceId,
- ObjectId: mockedTypeId,
- }).Return(&pb.RpcObjectShowResponse{
- ObjectView: &model.ObjectView{
- RootId: mockedTypeId,
- Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedTypeId,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
diff --git a/core/api/internal/search/service_test.go b/core/api/internal/search/service_test.go
index 8a55a0b9b6..233b6ee4f3 100644
--- a/core/api/internal/search/service_test.go
+++ b/core/api/internal/search/service_test.go
@@ -275,20 +275,8 @@ func TestSearchService_GlobalSearch(t *testing.T) {
},
},
},
- },
- },
- Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
- }, nil).Once()
-
- // Mock type resolution
- fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
- SpaceId: mockedSpaceId,
- ObjectId: mockedType,
- }).Return(&pb.RpcObjectShowResponse{
- ObjectView: &model.ObjectView{
- RootId: mockedType,
- Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedType,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedType),
@@ -298,7 +286,7 @@ func TestSearchService_GlobalSearch(t *testing.T) {
},
},
Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
- }).Once()
+ }, nil).Once()
// Mock participant details
fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
@@ -357,13 +345,13 @@ func TestSearchService_GlobalSearch(t *testing.T) {
} else if detail.Id == "last_modified_date" {
require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["date"])
} else if detail.Id == "created_by" {
- require.Equal(t, mockedParticipantId, detail.Details["details"].(space.Member).Id)
- require.Equal(t, mockedParticipantName, detail.Details["details"].(space.Member).Name)
- require.Equal(t, gatewayUrl+"/image/"+mockedParticipantImage, detail.Details["details"].(space.Member).Icon)
- require.Equal(t, mockedParticipantIdentity, detail.Details["details"].(space.Member).Identity)
- require.Equal(t, mockedParticipantGlobalName, detail.Details["details"].(space.Member).GlobalName)
+ require.Equal(t, mockedParticipantId, detail.Details["object"].(space.Member).Id)
+ require.Equal(t, mockedParticipantName, detail.Details["object"].(space.Member).Name)
+ require.Equal(t, gatewayUrl+"/image/"+mockedParticipantImage, detail.Details["object"].(space.Member).Icon)
+ require.Equal(t, mockedParticipantIdentity, detail.Details["object"].(space.Member).Identity)
+ require.Equal(t, mockedParticipantGlobalName, detail.Details["object"].(space.Member).GlobalName)
} else if detail.Id == "last_modified_by" {
- require.Equal(t, mockedParticipantId, detail.Details["details"].(space.Member).Id)
+ require.Equal(t, mockedParticipantId, detail.Details["object"].(space.Member).Id)
}
}
@@ -473,6 +461,7 @@ func TestSearchService_Search(t *testing.T) {
RootId: mockedRootId,
Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedRootId,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedObjectId),
@@ -484,20 +473,8 @@ func TestSearchService_Search(t *testing.T) {
},
},
},
- },
- },
- Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
- }).Once()
-
- // Mock type resolution
- fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
- SpaceId: mockedSpaceId,
- ObjectId: mockedType,
- }).Return(&pb.RpcObjectShowResponse{
- ObjectView: &model.ObjectView{
- RootId: mockedType,
- Details: []*model.ObjectViewDetailsSet{
{
+ Id: mockedType,
Details: &types.Struct{
Fields: map[string]*types.Value{
bundle.RelationKeyId.String(): pbtypes.String(mockedType),
From 280d63ccd00c1306ef910571f74f0654ab05f163 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sat, 15 Feb 2025 13:29:43 +0100
Subject: [PATCH 18/31] GO-4459: Return custom relations in details of object
response
---
core/api/internal/object/model.go | 20 +--
core/api/internal/object/service.go | 149 ++++++++++++++---------
core/api/internal/object/service_test.go | 135 ++++++++++----------
core/api/internal/search/service_test.go | 47 ++++---
core/api/util/util.go | 26 ++++
5 files changed, 225 insertions(+), 152 deletions(-)
diff --git a/core/api/internal/object/model.go b/core/api/internal/object/model.go
index 5846100ae0..b83284b3ce 100644
--- a/core/api/internal/object/model.go
+++ b/core/api/internal/object/model.go
@@ -29,13 +29,14 @@ type Object struct {
}
type Block struct {
- Id string `json:"id" example:"64394517de52ad5acb89c66c"` // The id of the block
- ChildrenIds []string `json:"children_ids" example:"['6797ce8ecda913cde14b02dc']"` // The ids of the block's children
- BackgroundColor string `json:"background_color" example:"red"` // The background color of the block
- Align string `json:"align" enums:"AlignLeft,AlignCenter,AlignRight,AlignJustify" example:"AlignLeft"` // The alignment of the block
- VerticalAlign string `json:"vertical_align" enums:"VerticalAlignTop,VerticalAlignMiddle,VerticalAlignBottom" example:"VerticalAlignTop"` // The vertical alignment of the block
- Text *Text `json:"text,omitempty"` // The text of the block, if applicable
- File *File `json:"file,omitempty"` // The file of the block, if applicable
+ Id string `json:"id" example:"64394517de52ad5acb89c66c"` // The id of the block
+ ChildrenIds []string `json:"children_ids" example:"['6797ce8ecda913cde14b02dc']"` // The ids of the block's children
+ BackgroundColor string `json:"background_color" example:"red"` // The background color of the block
+ Align string `json:"align" enums:"AlignLeft,AlignCenter,AlignRight,AlignJustify" example:"AlignLeft"` // The alignment of the block
+ VerticalAlign string `json:"vertical_align" enums:"VerticalAlignTop,VerticalAlignMiddle,VerticalAlignBottom" example:"VerticalAlignTop"` // The vertical alignment of the block
+ Text *Text `json:"text,omitempty"` // The text of the block, if applicable
+ File *File `json:"file,omitempty"` // The file of the block, if applicable
+ Relation *Relation `json:"relation,omitempty"` // The relation of the block, if applicable
}
type Text struct {
@@ -58,6 +59,11 @@ type File struct {
Style string `json:"style"` // The style of the file
}
+// TODO: fill in the relation struct
+type Relation struct {
+ Id string
+}
+
type Detail struct {
Id string `json:"id" enums:"last_modified_date,last_modified_by,created_date,created_by,last_opened_date,tags" example:"last_modified_date"` // The id of the detail
Details map[string]interface{} `json:"details"` // The details
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 10b074bd57..2ec4ba64b4 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -7,10 +7,12 @@ import (
"time"
"github.com/gogo/protobuf/types"
+ "github.com/iancoleman/strcase"
"github.com/anyproto/anytype-heart/core/api/internal/space"
"github.com/anyproto/anytype-heart/core/api/pagination"
"github.com/anyproto/anytype-heart/core/api/util"
+ "github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb/service"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
@@ -454,75 +456,94 @@ func (s *ObjectService) getTypeFromDetails(typeId string, details []*model.Objec
}
}
-// getDetails returns the list of details from the ObjectShowResponse.
+// getDetails returns a list of details by iterating over all relations found in the RelationLinks and mapping their format and value.
func (s *ObjectService) getDetails(resp *pb.RpcObjectShowResponse) []Detail {
relationFormatMap := s.getRelationFormatMap(resp.ObjectView.RelationLinks)
- creator := resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyCreator.String()].GetStringValue()
- lastModifiedBy := resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastModifiedBy.String()].GetStringValue()
-
- var creatorId, lastModifiedById string
- for _, detail := range resp.ObjectView.Details {
- if detail.Id == creator {
- creatorId = detail.Id
- }
- if detail.Id == lastModifiedBy {
- lastModifiedById = detail.Id
+ linkedRelations := resp.ObjectView.RelationLinks
+ primaryDetailFields := resp.ObjectView.Details[0].Details.Fields
+
+ var details []Detail
+ for _, r := range linkedRelations {
+ if val, ok := primaryDetailFields[r.Key]; ok {
+ relName := s.getRelationName(r.Key, resp)
+ format := relationFormatMap[r.Key]
+ details = append(details, Detail{
+ Id: strcase.ToSnake(relName),
+ Details: map[string]interface{}{
+ "name": relName,
+ "type": format,
+ format: s.convertValue(val, format, r.Key, resp.ObjectView.Details),
+ },
+ })
}
}
+ return details
+}
- memberLastModifiedBy, err := s.spaceService.GetMember(context.Background(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), lastModifiedById)
+// getRelationName returns the relation name from the RelationKey or the resolved relation name.
+func (s *ObjectService) getRelationName(key string, resp *pb.RpcObjectShowResponse) string {
+ relation, err := bundle.GetRelation(domain.RelationKey(key))
if err != nil {
- memberLastModifiedBy = space.Member{}
+ relation, err = util.ResolveRelationKeyToRelationName(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), key)
+ if err != nil {
+ return key
+ }
}
- memberCreator, err := s.spaceService.GetMember(context.Background(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), creatorId)
- if err != nil {
- memberCreator = space.Member{}
+ // custom relation names
+ if key == bundle.RelationKeyCreator.String() {
+ return "Created By"
+ } else if key == bundle.RelationKeyCreatedDate.String() {
+ return "Created Date"
}
- return []Detail{
- {
- Id: "last_modified_date",
- Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyLastModifiedDate.String()],
- "date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastModifiedDate.String()].GetNumberValue()),
- },
- },
- {
- Id: "last_modified_by",
- Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyLastModifiedBy.String()],
- "object": memberLastModifiedBy,
- },
- },
- {
- Id: "created_date",
- Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyCreatedDate.String()],
- "date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyCreatedDate.String()].GetNumberValue()),
- },
- },
- {
- Id: "created_by",
- Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyCreator.String()],
- "object": memberCreator,
- },
- },
- {
- Id: "last_opened_date",
- Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyLastOpenedDate.String()],
- "date": PosixToISO8601(resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyLastOpenedDate.String()].GetNumberValue()),
- },
- },
- {
- Id: "tags",
- Details: map[string]interface{}{
- "type": relationFormatMap[bundle.RelationKeyTag.String()],
- "multi_select": s.getTags(resp),
- },
- },
+ return relation.Name
+}
+
+// convertValue converts a protobuf types.Value into a native Go value.
+func (s *ObjectService) convertValue(value *types.Value, format string, key string, details []*model.ObjectViewDetailsSet) interface{} {
+ switch kind := value.Kind.(type) {
+ case *types.Value_NullValue:
+ return nil
+ case *types.Value_NumberValue:
+ if format == "date" {
+ return PosixToISO8601(kind.NumberValue)
+ }
+ return kind.NumberValue
+ case *types.Value_StringValue:
+ if key == bundle.RelationKeyCreator.String() || key == bundle.RelationKeyLastModifiedBy.String() {
+ member, err := s.spaceService.GetMember(context.Background(), details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), kind.StringValue)
+ if err != nil {
+ return nil
+ }
+ return member
+ }
+ return kind.StringValue
+ case *types.Value_BoolValue:
+ return kind.BoolValue
+ case *types.Value_StructValue:
+ m := make(map[string]interface{})
+ for k, v := range kind.StructValue.Fields {
+ m[k] = s.convertValue(v, format, key, details)
+ }
+ return m
+ case *types.Value_ListValue:
+ var list []interface{}
+ for _, v := range kind.ListValue.Values {
+ list = append(list, s.convertValue(v, format, key, details))
+ }
+
+ if format == "select" || format == "multi_select" {
+ return s.getTags(&pb.RpcObjectShowResponse{
+ ObjectView: &model.ObjectView{
+ Details: details,
+ },
+ })
+ }
+
+ return list
+ default:
+ return nil
}
}
@@ -532,6 +553,8 @@ func (s *ObjectService) getRelationFormatMap(relationLinks []*model.RelationLink
var mu sync.Mutex
mu.Lock()
+ relationFormatToName[int32(model.RelationFormat_longtext)] = "text"
+ relationFormatToName[int32(model.RelationFormat_shorttext)] = "text"
relationFormatToName[int32(model.RelationFormat_tag)] = "multi_select"
relationFormatToName[int32(model.RelationFormat_status)] = "select"
@@ -576,6 +599,7 @@ func (s *ObjectService) getBlocks(resp *pb.RpcObjectShowResponse) []Block {
for _, block := range resp.ObjectView.Blocks {
var text *Text
var file *File
+ var relation *Relation
switch content := block.Content.(type) {
case *model.BlockContentOfText:
@@ -598,8 +622,12 @@ func (s *ObjectService) getBlocks(resp *pb.RpcObjectShowResponse) []Block {
State: model.BlockContentFileState_name[int32(content.File.State)],
Style: model.BlockContentFileStyle_name[int32(content.File.Style)],
}
- // TODO: other content types?
+ case *model.BlockContentOfRelation:
+ relation = &Relation{
+ Id: content.Relation.Key,
+ }
}
+ // TODO: other content types?
blocks = append(blocks, Block{
Id: block.Id,
@@ -609,6 +637,7 @@ func (s *ObjectService) getBlocks(resp *pb.RpcObjectShowResponse) []Block {
VerticalAlign: model.BlockVerticalAlign_name[int32(block.VerticalAlign)],
Text: text,
File: file,
+ Relation: relation,
})
}
diff --git a/core/api/internal/object/service_test.go b/core/api/internal/object/service_test.go
index ed40c5b5ef..447f2f6913 100644
--- a/core/api/internal/object/service_test.go
+++ b/core/api/internal/object/service_test.go
@@ -27,6 +27,7 @@ const (
mockedObjectName = "mocked-object-name"
mockedObjectSnippet = "mocked-object-snippet"
mockedObjectIcon = "🔍"
+ mockedParticipantId = "mocked-participant-id"
mockedObjectTypeUniqueKey = "ot-page"
mockedTypeId = "mocked-type-id"
mockedTypeName = "mocked-type-name"
@@ -122,11 +123,21 @@ func TestObjectService_ListObjects(t *testing.T) {
bundle.RelationKeyName.String(): pbtypes.String(mockedObjectName),
bundle.RelationKeySnippet.String(): pbtypes.String(mockedObjectSnippet),
bundle.RelationKeyIconEmoji.String(): pbtypes.String(mockedObjectIcon),
- bundle.RelationKeyType.String(): pbtypes.String(mockedTypeId),
bundle.RelationKeyCreatedDate.String(): pbtypes.Float64(888888),
+ bundle.RelationKeyLastModifiedBy.String(): pbtypes.String(mockedParticipantId),
bundle.RelationKeyLastModifiedDate.String(): pbtypes.Float64(999999),
+ bundle.RelationKeyCreator.String(): pbtypes.String(mockedParticipantId),
bundle.RelationKeyLastOpenedDate.String(): pbtypes.Float64(0),
bundle.RelationKeySpaceId.String(): pbtypes.String(mockedSpaceId),
+ bundle.RelationKeyType.String(): pbtypes.String(mockedTypeId),
+ },
+ },
+ },
+ {
+ Id: mockedParticipantId,
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedParticipantId),
},
},
},
@@ -142,6 +153,32 @@ func TestObjectService_ListObjects(t *testing.T) {
},
},
},
+ RelationLinks: []*model.RelationLink{
+ {
+ Key: bundle.RelationKeyLastModifiedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyLastModifiedBy.String(),
+ Format: model.RelationFormat_object,
+ },
+ {
+ Key: bundle.RelationKeyCreatedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyCreator.String(),
+ Format: model.RelationFormat_object,
+ },
+ {
+ Key: bundle.RelationKeyLastOpenedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyTag.String(),
+ Format: model.RelationFormat_tag,
+ },
+ },
},
Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}).Once()
@@ -154,7 +191,7 @@ func TestObjectService_ListObjects(t *testing.T) {
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyId.String(),
Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(""),
+ Value: pbtypes.String(mockedParticipantId),
},
},
Keys: []string{
@@ -169,7 +206,11 @@ func TestObjectService_ListObjects(t *testing.T) {
}).Return(&pb.RpcObjectSearchResponse{
Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
Records: []*types.Struct{
- {},
+ {
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedParticipantId),
+ },
+ },
},
}).Twice()
@@ -187,17 +228,17 @@ func TestObjectService_ListObjects(t *testing.T) {
require.Equal(t, mockedObjectName, objects[0].Name)
require.Equal(t, mockedObjectSnippet, objects[0].Snippet)
require.Equal(t, mockedObjectIcon, objects[0].Icon)
- require.Equal(t, 6, len(objects[0].Details))
+ require.Equal(t, 5, len(objects[0].Details))
for _, detail := range objects[0].Details {
if detail.Id == "created_date" {
require.Equal(t, "1970-01-11T06:54:48Z", detail.Details["date"])
} else if detail.Id == "created_by" {
- require.Empty(t, detail.Details["created_by"])
+ require.Equal(t, mockedParticipantId, detail.Details["object"].(space.Member).Id)
} else if detail.Id == "last_modified_date" {
require.Equal(t, "1970-01-12T13:46:39Z", detail.Details["date"])
} else if detail.Id == "last_modified_by" {
- require.Empty(t, detail.Details["last_modified_by"])
+ require.Equal(t, mockedParticipantId, detail.Details["object"].(space.Member).Id)
} else if detail.Id == "last_opened_date" {
require.Equal(t, "1970-01-01T00:00:00Z", detail.Details["date"])
} else if detail.Id == "tags" {
@@ -276,36 +317,35 @@ func TestObjectService_GetObject(t *testing.T) {
},
},
},
+ RelationLinks: []*model.RelationLink{
+ {
+ Key: bundle.RelationKeyLastModifiedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyLastModifiedBy.String(),
+ Format: model.RelationFormat_object,
+ },
+ {
+ Key: bundle.RelationKeyCreatedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyCreator.String(),
+ Format: model.RelationFormat_object,
+ },
+ {
+ Key: bundle.RelationKeyLastOpenedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyTag.String(),
+ Format: model.RelationFormat_tag,
+ },
+ },
},
}, nil).Once()
- // Mock participant details
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- Operator: model.BlockContentDataviewFilter_No,
- RelationKey: bundle.RelationKeyId.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(""),
- },
- },
- Keys: []string{
- bundle.RelationKeyId.String(),
- bundle.RelationKeyName.String(),
- bundle.RelationKeyIconEmoji.String(),
- bundle.RelationKeyIconImage.String(),
- bundle.RelationKeyIdentity.String(),
- bundle.RelationKeyGlobalName.String(),
- bundle.RelationKeyParticipantPermissions.String(),
- },
- }).Return(&pb.RpcObjectSearchResponse{
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
- Records: []*types.Struct{
- {},
- },
- }).Twice()
-
// when
object, err := fx.GetObject(ctx, mockedSpaceId, mockedObjectId)
@@ -320,7 +360,7 @@ func TestObjectService_GetObject(t *testing.T) {
require.Equal(t, mockedObjectName, object.Name)
require.Equal(t, mockedObjectSnippet, object.Snippet)
require.Equal(t, mockedObjectName, object.Icon)
- require.Equal(t, 6, len(object.Details))
+ require.Equal(t, 3, len(object.Details))
for _, detail := range object.Details {
if detail.Id == "created_date" {
@@ -430,33 +470,6 @@ func TestObjectService_CreateObject(t *testing.T) {
Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}).Once()
- // Mock participant details
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- Operator: model.BlockContentDataviewFilter_No,
- RelationKey: bundle.RelationKeyId.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(""),
- },
- },
- Keys: []string{
- bundle.RelationKeyId.String(),
- bundle.RelationKeyName.String(),
- bundle.RelationKeyIconEmoji.String(),
- bundle.RelationKeyIconImage.String(),
- bundle.RelationKeyIdentity.String(),
- bundle.RelationKeyGlobalName.String(),
- bundle.RelationKeyParticipantPermissions.String(),
- },
- }).Return(&pb.RpcObjectSearchResponse{
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
- Records: []*types.Struct{
- {},
- },
- }).Twice()
-
// when
object, err := fx.CreateObject(ctx, mockedSpaceId, CreateObjectRequest{
Name: mockedObjectName,
diff --git a/core/api/internal/search/service_test.go b/core/api/internal/search/service_test.go
index 233b6ee4f3..c6d1e023ad 100644
--- a/core/api/internal/search/service_test.go
+++ b/core/api/internal/search/service_test.go
@@ -284,7 +284,30 @@ func TestSearchService_GlobalSearch(t *testing.T) {
},
},
},
+ RelationLinks: []*model.RelationLink{
+ {
+ Key: bundle.RelationKeyLastModifiedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyLastModifiedBy.String(),
+ Format: model.RelationFormat_object,
+ },
+ {
+ Key: bundle.RelationKeyCreatedDate.String(),
+ Format: model.RelationFormat_date,
+ },
+ {
+ Key: bundle.RelationKeyCreator.String(),
+ Format: model.RelationFormat_object,
+ },
+ {
+ Key: bundle.RelationKeyTag.String(),
+ Format: model.RelationFormat_tag,
+ },
+ },
},
+
Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}, nil).Once()
@@ -486,30 +509,6 @@ func TestSearchService_Search(t *testing.T) {
Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
}).Once()
- // Mock participant details
- fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
- SpaceId: mockedSpaceId,
- Filters: []*model.BlockContentDataviewFilter{
- {
- Operator: model.BlockContentDataviewFilter_No,
- RelationKey: bundle.RelationKeyId.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(""),
- },
- },
- Keys: []string{bundle.RelationKeyId.String(),
- bundle.RelationKeyName.String(),
- bundle.RelationKeyIconEmoji.String(),
- bundle.RelationKeyIconImage.String(),
- bundle.RelationKeyIdentity.String(),
- bundle.RelationKeyGlobalName.String(),
- bundle.RelationKeyParticipantPermissions.String(),
- },
- }).Return(&pb.RpcObjectSearchResponse{
- Records: []*types.Struct{},
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
- }).Twice()
-
// when
objects, total, hasMore, err := fx.Search(ctx, mockedSpaceId, SearchRequest{Query: mockedSearchTerm, Types: []string{}, Sort: SortOptions{Direction: "desc", Timestamp: "last_modified_date"}}, offset, limit)
diff --git a/core/api/util/util.go b/core/api/util/util.go
index c8ce71dec2..db6e3e427f 100644
--- a/core/api/util/util.go
+++ b/core/api/util/util.go
@@ -54,3 +54,29 @@ func ResolveUniqueKeyToTypeId(mw service.ClientCommandsServer, spaceId string, u
return resp.Records[0].Fields[bundle.RelationKeyId.String()].GetStringValue(), nil
}
+
+func ResolveRelationKeyToRelationName(mw service.ClientCommandsServer, spaceId string, relationKey string) (relation *model.Relation, err error) {
+ resp := mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
+ SpaceId: spaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyRelationKey.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String(relationKey),
+ },
+ },
+ Keys: []string{bundle.RelationKeyId.String()},
+ })
+
+ if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
+ return &model.Relation{}, ErrFailedSearchType
+ }
+
+ if len(resp.Records) == 0 {
+ return &model.Relation{}, ErrorTypeNotFound
+ }
+
+ return &model.Relation{
+ Name: resp.Records[0].Fields[bundle.RelationKeyName.String()].GetStringValue(),
+ }, nil
+}
From 820a894bf135b5fb815c8903623109c93236b888 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sat, 15 Feb 2025 20:07:13 +0100
Subject: [PATCH 19/31] GO-4459: Add exclusion of system relations in object
details
---
core/api/internal/object/service.go | 94 +++++++++++++++++++----------
core/api/util/util.go | 8 ++-
2 files changed, 70 insertions(+), 32 deletions(-)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 2ec4ba64b4..0079b90952 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -3,8 +3,6 @@ package object
import (
"context"
"errors"
- "sync"
- "time"
"github.com/gogo/protobuf/types"
"github.com/iancoleman/strcase"
@@ -462,15 +460,58 @@ func (s *ObjectService) getDetails(resp *pb.RpcObjectShowResponse) []Detail {
linkedRelations := resp.ObjectView.RelationLinks
primaryDetailFields := resp.ObjectView.Details[0].Details.Fields
+ // system relations to be excluded
+ excludeRelations := map[string]bool{
+ bundle.RelationKeyId.String(): true,
+ bundle.RelationKeySpaceId.String(): true,
+ bundle.RelationKeyName.String(): true,
+ bundle.RelationKeyIconEmoji.String(): true,
+ bundle.RelationKeyIconImage.String(): true,
+ bundle.RelationKeyType.String(): true,
+ bundle.RelationKeyLayout.String(): true,
+ bundle.RelationKeyIsFavorite.String(): true,
+ bundle.RelationKeyIsArchived.String(): true,
+ bundle.RelationKeyIsDeleted.String(): true,
+ bundle.RelationKeyIsHidden.String(): true,
+ bundle.RelationKeyWorkspaceId.String(): true,
+ bundle.RelationKeyInternalFlags.String(): true,
+ bundle.RelationKeyRestrictions.String(): true,
+ bundle.RelationKeyOrigin.String(): true,
+ bundle.RelationKeySnippet.String(): true,
+ bundle.RelationKeySyncStatus.String(): true,
+ bundle.RelationKeySyncError.String(): true,
+ bundle.RelationKeySyncDate.String(): true,
+ bundle.RelationKeyCoverId.String(): true,
+ bundle.RelationKeyCoverType.String(): true,
+ bundle.RelationKeyCoverScale.String(): true,
+ bundle.RelationKeyCoverX.String(): true,
+ bundle.RelationKeyCoverY.String(): true,
+ bundle.RelationKeyMentions.String(): true,
+ bundle.RelationKeyOldAnytypeID.String(): true,
+ bundle.RelationKeySource.String(): true,
+ bundle.RelationKeySourceFilePath.String(): true,
+ bundle.RelationKeyImportType.String(): true,
+ bundle.RelationKeyTargetObjectType.String(): true,
+ bundle.RelationKeyFeaturedRelations.String(): true,
+ bundle.RelationKeySetOf.String(): true,
+ bundle.RelationKeyLinks.String(): true,
+ bundle.RelationKeyBacklinks.String(): true,
+ bundle.RelationKeySourceObject.String(): true,
+ }
+
var details []Detail
for _, r := range linkedRelations {
+ if _, isExcluded := excludeRelations[r.Key]; isExcluded {
+ continue
+ }
+
if val, ok := primaryDetailFields[r.Key]; ok {
- relName := s.getRelationName(r.Key, resp)
+ id, name := s.getRelation(r.Key, resp)
format := relationFormatMap[r.Key]
details = append(details, Detail{
- Id: strcase.ToSnake(relName),
+ Id: id,
Details: map[string]interface{}{
- "name": relName,
+ "name": name,
"type": format,
format: s.convertValue(val, format, r.Key, resp.ObjectView.Details),
},
@@ -480,24 +521,25 @@ func (s *ObjectService) getDetails(resp *pb.RpcObjectShowResponse) []Detail {
return details
}
-// getRelationName returns the relation name from the RelationKey or the resolved relation name.
-func (s *ObjectService) getRelationName(key string, resp *pb.RpcObjectShowResponse) string {
+// getRelationName returns the relation id and relation name from the ObjectShowResponse.
+func (s *ObjectService) getRelation(key string, resp *pb.RpcObjectShowResponse) (id string, name string) {
relation, err := bundle.GetRelation(domain.RelationKey(key))
if err != nil {
relation, err = util.ResolveRelationKeyToRelationName(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), key)
if err != nil {
- return key
+ return strcase.ToSnake(key), key
}
+ return key, relation.Name
}
- // custom relation names
+ // special cases of relation keys and names
if key == bundle.RelationKeyCreator.String() {
- return "Created By"
+ return "created_by", "Created By"
} else if key == bundle.RelationKeyCreatedDate.String() {
- return "Created Date"
+ return "created_date", "Created Date"
}
- return relation.Name
+ return strcase.ToSnake(key), relation.Name
}
// convertValue converts a protobuf types.Value into a native Go value.
@@ -507,7 +549,7 @@ func (s *ObjectService) convertValue(value *types.Value, format string, key stri
return nil
case *types.Value_NumberValue:
if format == "date" {
- return PosixToISO8601(kind.NumberValue)
+ return util.PosixToISO8601(kind.NumberValue)
}
return kind.NumberValue
case *types.Value_StringValue:
@@ -534,11 +576,7 @@ func (s *ObjectService) convertValue(value *types.Value, format string, key stri
}
if format == "select" || format == "multi_select" {
- return s.getTags(&pb.RpcObjectShowResponse{
- ObjectView: &model.ObjectView{
- Details: details,
- },
- })
+ return s.getTags(key, details)
}
return list
@@ -549,10 +587,10 @@ func (s *ObjectService) convertValue(value *types.Value, format string, key stri
// getRelationFormatMapFromResponse returns the map of relation key to relation format from the ObjectShowResponse.
func (s *ObjectService) getRelationFormatMap(relationLinks []*model.RelationLink) map[string]string {
- var relationFormatToName = model.RelationFormat_name
- var mu sync.Mutex
-
- mu.Lock()
+ relationFormatToName := make(map[int32]string, len(model.RelationFormat_name))
+ for k, v := range model.RelationFormat_name {
+ relationFormatToName[k] = v
+ }
relationFormatToName[int32(model.RelationFormat_longtext)] = "text"
relationFormatToName[int32(model.RelationFormat_shorttext)] = "text"
relationFormatToName[int32(model.RelationFormat_tag)] = "multi_select"
@@ -562,23 +600,22 @@ func (s *ObjectService) getRelationFormatMap(relationLinks []*model.RelationLink
for _, detail := range relationLinks {
relationFormatMap[detail.Key] = relationFormatToName[int32(detail.Format)]
}
- mu.Unlock()
return relationFormatMap
}
// getTags returns the list of tags from the ObjectShowResponse
-func (s *ObjectService) getTags(resp *pb.RpcObjectShowResponse) []Tag {
+func (s *ObjectService) getTags(key string, details []*model.ObjectViewDetailsSet) []Tag {
tags := []Tag{}
- tagField, ok := resp.ObjectView.Details[0].Details.Fields["tag"]
+ tagField, ok := details[0].Details.Fields[key]
if !ok || tagField.GetListValue() == nil {
return tags
}
for _, tagId := range tagField.GetListValue().Values {
id := tagId.GetStringValue()
- for _, detail := range resp.ObjectView.Details {
+ for _, detail := range details {
if detail.Id == id {
tags = append(tags, Tag{
Id: id,
@@ -643,8 +680,3 @@ func (s *ObjectService) getBlocks(resp *pb.RpcObjectShowResponse) []Block {
return blocks
}
-
-func PosixToISO8601(posix float64) string {
- t := time.Unix(int64(posix), 0).UTC()
- return t.Format(time.RFC3339)
-}
diff --git a/core/api/util/util.go b/core/api/util/util.go
index db6e3e427f..25eacf1d25 100644
--- a/core/api/util/util.go
+++ b/core/api/util/util.go
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
+ "time"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb/service"
@@ -17,6 +18,11 @@ var (
ErrorTypeNotFound = errors.New("type not found")
)
+func PosixToISO8601(posix float64) string {
+ t := time.Unix(int64(posix), 0).UTC()
+ return t.Format(time.RFC3339)
+}
+
// GetIconFromEmojiOrImage returns the icon to use for the object, which can be either an emoji or an image url
func GetIconFromEmojiOrImage(accountInfo *model.AccountInfo, iconEmoji string, iconImage string) string {
if iconEmoji != "" {
@@ -65,7 +71,7 @@ func ResolveRelationKeyToRelationName(mw service.ClientCommandsServer, spaceId s
Value: pbtypes.String(relationKey),
},
},
- Keys: []string{bundle.RelationKeyId.String()},
+ Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeyName.String()},
})
if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
From ce783a72e31b470cc306ba3d5d43cf422855af62 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 16 Feb 2025 12:00:47 +0100
Subject: [PATCH 20/31] GO-4459: Fix security definition to ApiKey auth
---
core/api/docs/docs.go | 26 ++++++++++++++++++++------
core/api/docs/swagger.json | 26 ++++++++++++++++++++------
core/api/docs/swagger.yaml | 18 +++++++++++++-----
core/api/service.go | 4 +++-
4 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 0c3db26bad..019faf5d95 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -1356,6 +1356,14 @@ const docTemplate = `{
"type": "string",
"example": "64394517de52ad5acb89c66c"
},
+ "relation": {
+ "description": "The relation of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Relation"
+ }
+ ]
+ },
"text": {
"description": "The text of the block, if applicable",
"allOf": [
@@ -1560,6 +1568,14 @@ const docTemplate = `{
}
}
},
+ "object.Relation": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ }
+ }
+ },
"object.Template": {
"type": "object",
"properties": {
@@ -2140,13 +2156,11 @@ const docTemplate = `{
}
},
"securityDefinitions": {
- "BasicAuth": {
- "type": "basic"
+ "ApiKeyAuth": {
+ "type": "apiKey",
+ "name": "Authorization",
+ "in": "header"
}
- },
- "externalDocs": {
- "description": "OpenAPI",
- "url": "https://swagger.io/resources/open-api/"
}
}`
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index 223b833839..f0af08881c 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -1350,6 +1350,14 @@
"type": "string",
"example": "64394517de52ad5acb89c66c"
},
+ "relation": {
+ "description": "The relation of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Relation"
+ }
+ ]
+ },
"text": {
"description": "The text of the block, if applicable",
"allOf": [
@@ -1554,6 +1562,14 @@
}
}
},
+ "object.Relation": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ }
+ }
+ },
"object.Template": {
"type": "object",
"properties": {
@@ -2134,12 +2150,10 @@
}
},
"securityDefinitions": {
- "BasicAuth": {
- "type": "basic"
+ "ApiKeyAuth": {
+ "type": "apiKey",
+ "name": "Authorization",
+ "in": "header"
}
- },
- "externalDocs": {
- "description": "OpenAPI",
- "url": "https://swagger.io/resources/open-api/"
}
}
\ No newline at end of file
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 0dd2b302ac..c4dfe63d13 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -56,6 +56,10 @@ definitions:
description: The id of the block
example: 64394517de52ad5acb89c66c
type: string
+ relation:
+ allOf:
+ - $ref: '#/definitions/object.Relation'
+ description: The relation of the block, if applicable
text:
allOf:
- $ref: '#/definitions/object.Text'
@@ -205,6 +209,11 @@ definitions:
- $ref: '#/definitions/object.Object'
description: The object
type: object
+ object.Relation:
+ properties:
+ id:
+ type: string
+ type: object
object.Template:
properties:
icon:
@@ -615,9 +624,6 @@ definitions:
type: string
type: object
type: object
-externalDocs:
- description: OpenAPI
- url: https://swagger.io/resources/open-api/
host: localhost:31009
info:
contact:
@@ -1476,6 +1482,8 @@ paths:
tags:
- lists
securityDefinitions:
- BasicAuth:
- type: basic
+ ApiKeyAuth:
+ in: header
+ name: Authorization
+ type: apiKey
swagger: "2.0"
diff --git a/core/api/service.go b/core/api/service.go
index 6027337b64..d6cb17d475 100644
--- a/core/api/service.go
+++ b/core/api/service.go
@@ -60,7 +60,9 @@ func (s *apiService) Name() (name string) {
// @license.url https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md
// @host localhost:31009
// @BasePath /v1
-// @securityDefinitions.basic BasicAuth
+// @securityDefinitions.apikey ApiKeyAuth
+// @in header
+// @name Authorization
// @externalDocs.description OpenAPI
// @externalDocs.url https://swagger.io/resources/open-api/
func (s *apiService) Init(a *app.App) (err error) {
From 0a0ef5317dcd2dd0b706509cba51a5a0d60ea51c Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 16 Feb 2025 12:59:37 +0100
Subject: [PATCH 21/31] GO-4459: Upgrade to OpenAPI specification v3.1 and
swaggo/swag v2
---
core/api/docs/docs.go | 2173 +-------------------------
core/api/docs/swagger.json | 2165 +-------------------------
core/api/docs/swagger.yaml | 2204 +++++++++++++++------------
core/api/internal/export/handler.go | 1 +
core/api/internal/list/handler.go | 25 +-
core/api/internal/list/service.go | 8 +-
core/api/internal/object/handler.go | 15 +-
core/api/internal/search/handler.go | 2 +
core/api/internal/space/handler.go | 9 +-
core/api/server/router.go | 2 +-
core/api/service.go | 30 +-
go.mod | 12 +-
go.sum | 16 +
13 files changed, 1276 insertions(+), 5386 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 019faf5d95..2faeb5526a 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -1,2175 +1,24 @@
-// Package docs Code generated by swaggo/swag. DO NOT EDIT
+// Code generated by swaggo/swag. DO NOT EDIT.
+
package docs
-import "github.com/swaggo/swag"
+import "github.com/swaggo/swag/v2"
const docTemplate = `{
"schemes": {{ marshal .Schemes }},
- "swagger": "2.0",
- "info": {
- "description": "{{escape .Description}}",
- "title": "{{.Title}}",
- "termsOfService": "https://anytype.io/terms_of_use",
- "contact": {
- "name": "Anytype Support",
- "url": "https://anytype.io/contact",
- "email": "support@anytype.io"
- },
- "license": {
- "name": "Any Source Available License 1.0",
- "url": "https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md"
- },
- "version": "{{.Version}}"
- },
- "host": "{{.Host}}",
- "basePath": "{{.BasePath}}",
- "paths": {
- "/auth/display_code": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "auth"
- ],
- "summary": "Start new challenge",
- "parameters": [
- {
- "type": "string",
- "description": "App name requesting the challenge",
- "name": "app_name",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Challenge ID",
- "schema": {
- "$ref": "#/definitions/auth.DisplayCodeResponse"
- }
- },
- "400": {
- "description": "Invalid input",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/auth/token": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "auth"
- ],
- "summary": "Retrieve token",
- "parameters": [
- {
- "type": "string",
- "description": "Challenge ID",
- "name": "challenge_id",
- "in": "query",
- "required": true
- },
- {
- "type": "string",
- "description": "4-digit code retrieved from Anytype Desktop app",
- "name": "code",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Authentication token",
- "schema": {
- "$ref": "#/definitions/auth.TokenResponse"
- }
- },
- "400": {
- "description": "Invalid input",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/search": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "search"
- ],
- "summary": "Search objects across all spaces",
- "parameters": [
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- },
- {
- "description": "Search parameters",
- "name": "request",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/search.SearchRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "List spaces",
- "parameters": [
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of spaces",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-space_Space"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "Create space",
- "parameters": [
- {
- "description": "Space to create",
- "name": "name",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/space.CreateSpaceRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Space created successfully",
- "schema": {
- "$ref": "#/definitions/space.SpaceResponse"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "423": {
- "description": "Rate limit exceeded",
- "schema": {
- "$ref": "#/definitions/util.RateLimitError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "Get space",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Space",
- "schema": {
- "$ref": "#/definitions/space.SpaceResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Space not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/members": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "List members",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of members",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-space_Member"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/members/{member_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "Get member",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Member ID",
- "name": "member_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Member",
- "schema": {
- "$ref": "#/definitions/space.MemberResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Member not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/objects": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "List objects",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "Create object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "description": "Object to create",
- "name": "object",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/object.CreateObjectRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "The created object",
- "schema": {
- "$ref": "#/definitions/object.ObjectResponse"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "423": {
- "description": "Rate limit exceeded",
- "schema": {
- "$ref": "#/definitions/util.RateLimitError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/objects/{object_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "Get object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Object ID",
- "name": "object_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The requested object",
- "schema": {
- "$ref": "#/definitions/object.ObjectResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "delete": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "Delete object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Object ID",
- "name": "object_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The deleted object",
- "schema": {
- "$ref": "#/definitions/object.ObjectResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "403": {
- "description": "Forbidden",
- "schema": {
- "$ref": "#/definitions/util.ForbiddenError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "423": {
- "description": "Rate limit exceeded",
- "schema": {
- "$ref": "#/definitions/util.RateLimitError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/objects/{object_id}/export/{format}": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "export"
- ],
- "summary": "Export object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Object ID",
- "name": "object_id",
- "in": "path",
- "required": true
- },
- {
- "enum": [
- "markdown",
- "protobuf"
- ],
- "type": "string",
- "description": "Export format",
- "name": "format",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Object exported successfully",
- "schema": {
- "$ref": "#/definitions/export.ObjectExportResponse"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/search": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "search"
- ],
- "summary": "Search objects within a space",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- },
- {
- "description": "Search parameters",
- "name": "request",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/search.SearchRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "List types",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of types",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Type"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types/{type_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "Get type",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Type ID",
- "name": "type_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The requested type",
- "schema": {
- "$ref": "#/definitions/object.TypeResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types/{type_id}/templates": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "List templates",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Type ID",
- "name": "type_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of templates",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Template"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types/{type_id}/templates/{template_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "Get template",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Type ID",
- "name": "type_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Template ID",
- "name": "template_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The requested template",
- "schema": {
- "$ref": "#/definitions/object.TemplateResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/v1/spaces/{space_id}/lists/{list_id}/objects": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Get objects in list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "type": "integer",
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Add objects to list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "description": "List of object IDs",
- "name": "objects",
- "in": "body",
- "required": true,
- "schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Objects added successfully",
- "schema": {
- "type": "string"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "delete": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Remove objects from list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "description": "List of object IDs",
- "name": "objects",
- "in": "body",
- "required": true,
- "schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Objects removed successfully",
- "schema": {
- "type": "string"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- }
- },
- "definitions": {
- "auth.DisplayCodeResponse": {
- "type": "object",
- "properties": {
- "challenge_id": {
- "description": "The challenge id associated with the displayed code and needed to solve the challenge for token",
- "type": "string",
- "example": "67647f5ecda913e9a2e11b26"
- }
- }
- },
- "auth.TokenResponse": {
- "type": "object",
- "properties": {
- "app_key": {
- "description": "The permanent app key",
- "type": "string",
- "example": "zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="
- },
- "session_token": {
- "description": "The ephemeral session token",
- "type": "string",
- "example": "eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"
- }
- }
- },
- "export.ObjectExportResponse": {
- "type": "object",
- "properties": {
- "path": {
- "description": "The path the object was exported to",
- "type": "string",
- "example": "/path/to/export"
- }
- }
- },
- "object.Block": {
- "type": "object",
- "properties": {
- "align": {
- "description": "The alignment of the block",
- "type": "string",
- "enum": [
- "AlignLeft",
- "AlignCenter",
- "AlignRight",
- "AlignJustify"
- ],
- "example": "AlignLeft"
- },
- "background_color": {
- "description": "The background color of the block",
- "type": "string",
- "example": "red"
- },
- "children_ids": {
- "description": "The ids of the block's children",
- "type": "array",
- "items": {
- "type": "string"
- },
- "example": [
- "['6797ce8ecda913cde14b02dc']"
- ]
- },
- "file": {
- "description": "The file of the block, if applicable",
- "allOf": [
- {
- "$ref": "#/definitions/object.File"
- }
- ]
- },
- "id": {
- "description": "The id of the block",
- "type": "string",
- "example": "64394517de52ad5acb89c66c"
- },
- "relation": {
- "description": "The relation of the block, if applicable",
- "allOf": [
- {
- "$ref": "#/definitions/object.Relation"
- }
- ]
- },
- "text": {
- "description": "The text of the block, if applicable",
- "allOf": [
- {
- "$ref": "#/definitions/object.Text"
- }
- ]
- },
- "vertical_align": {
- "description": "The vertical alignment of the block",
- "type": "string",
- "enum": [
- "VerticalAlignTop",
- "VerticalAlignMiddle",
- "VerticalAlignBottom"
- ],
- "example": "VerticalAlignTop"
- }
- }
- },
- "object.CreateObjectRequest": {
- "type": "object",
- "properties": {
- "body": {
- "description": "The body of the object",
- "type": "string",
- "example": "This is the body of the object. Markdown syntax is supported here."
- },
- "description": {
- "description": "The description of the object",
- "type": "string",
- "example": "This is a description of the object."
- },
- "icon": {
- "description": "The icon of the object",
- "type": "string",
- "example": "📄"
- },
- "name": {
- "description": "The name of the object",
- "type": "string",
- "example": "My object"
- },
- "object_type_unique_key": {
- "description": "The unique key of the object type",
- "type": "string",
- "example": "ot-page"
- },
- "source": {
- "description": "The source url, only applicable for bookmarks",
- "type": "string",
- "example": "https://bookmark-source.com"
- },
- "template_id": {
- "description": "The id of the template to use",
- "type": "string",
- "example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
- }
- }
- },
- "object.Detail": {
- "type": "object",
- "properties": {
- "details": {
- "description": "The details",
- "type": "object",
- "additionalProperties": true
- },
- "id": {
- "description": "The id of the detail",
- "type": "string",
- "enum": [
- "last_modified_date",
- "last_modified_by",
- "created_date",
- "created_by",
- "last_opened_date",
- "tags"
- ],
- "example": "last_modified_date"
- }
- }
- },
- "object.File": {
- "type": "object",
- "properties": {
- "added_at": {
- "description": "The added at of the file",
- "type": "integer"
- },
- "hash": {
- "description": "The hash of the file",
- "type": "string"
- },
- "mime": {
- "description": "The mime of the file",
- "type": "string"
- },
- "name": {
- "description": "The name of the file",
- "type": "string"
- },
- "size": {
- "description": "The size of the file",
- "type": "integer"
- },
- "state": {
- "description": "The state of the file",
- "type": "string"
- },
- "style": {
- "description": "The style of the file",
- "type": "string"
- },
- "target_object_id": {
- "description": "The target object id of the file",
- "type": "string"
- },
- "type": {
- "description": "The type of the file",
- "type": "string"
- }
- }
- },
- "object.Object": {
- "type": "object",
- "properties": {
- "blocks": {
- "description": "The blocks of the object",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Block"
- }
- },
- "details": {
- "description": "The details of the object",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Detail"
- }
- },
- "icon": {
- "description": "The icon of the object",
- "type": "string",
- "example": "📄"
- },
- "id": {
- "description": "The id of the object",
- "type": "string",
- "example": "bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"
- },
- "layout": {
- "description": "The layout of the object",
- "type": "string",
- "example": "basic"
- },
- "name": {
- "description": "The name of the object",
- "type": "string",
- "example": "My object"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "object"
- },
- "root_id": {
- "description": "The id of the object's root",
- "type": "string",
- "example": "bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"
- },
- "snippet": {
- "description": "The snippet of the object, especially important for notes as they don't have a name",
- "type": "string",
- "example": "The beginning of the object body..."
- },
- "space_id": {
- "description": "The id of the space the object is in",
- "type": "string",
- "example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
- },
- "type": {
- "description": "The type of the object",
- "allOf": [
- {
- "$ref": "#/definitions/object.Type"
- }
- ]
- }
- }
- },
- "object.ObjectResponse": {
- "type": "object",
- "properties": {
- "object": {
- "description": "The object",
- "allOf": [
- {
- "$ref": "#/definitions/object.Object"
- }
- ]
- }
- }
- },
- "object.Relation": {
- "type": "object",
- "properties": {
- "id": {
- "type": "string"
- }
- }
- },
- "object.Template": {
- "type": "object",
- "properties": {
- "icon": {
- "description": "The icon of the template",
- "type": "string",
- "example": "📄"
- },
- "id": {
- "description": "The id of the template",
- "type": "string",
- "example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
- },
- "name": {
- "description": "The name of the template",
- "type": "string",
- "example": "My template"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "template"
- }
- }
- },
- "object.TemplateResponse": {
- "type": "object",
- "properties": {
- "template": {
- "description": "The template",
- "allOf": [
- {
- "$ref": "#/definitions/object.Template"
- }
- ]
- }
- }
- },
- "object.Text": {
- "type": "object",
- "properties": {
- "checked": {
- "description": "Whether the text is checked",
- "type": "boolean",
- "example": true
- },
- "color": {
- "description": "The color of the text",
- "type": "string",
- "example": "red"
- },
- "icon": {
- "description": "The icon of the text",
- "type": "string",
- "example": "📄"
- },
- "style": {
- "description": "The style of the text",
- "type": "string",
- "enum": [
- "Paragraph",
- "Header1",
- "Header2",
- "Header3",
- "Header4",
- "Quote",
- "Code",
- "Title",
- "Checkbox",
- "Marked",
- "Numbered",
- "Toggle",
- "Description",
- "Callout"
- ],
- "example": "Paragraph"
- },
- "text": {
- "description": "The text",
- "type": "string",
- "example": "Some text..."
- }
- }
- },
- "object.Type": {
- "type": "object",
- "properties": {
- "icon": {
- "description": "The icon of the type",
- "type": "string",
- "example": "📄"
- },
- "id": {
- "description": "The id of the type",
- "type": "string",
- "example": "bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"
- },
- "name": {
- "description": "The name of the type",
- "type": "string",
- "example": "Page"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "type"
- },
- "recommended_layout": {
- "description": "The recommended layout of the type",
- "type": "string",
- "example": "todo"
- },
- "unique_key": {
- "description": "The unique key of the type",
- "type": "string",
- "example": "ot-page"
- }
- }
- },
- "object.TypeResponse": {
- "type": "object",
- "properties": {
- "type": {
- "description": "The type",
- "allOf": [
- {
- "$ref": "#/definitions/object.Type"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-object_Object": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Object"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-object_Template": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Template"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-object_Type": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Type"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-space_Member": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/space.Member"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-space_Space": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/space.Space"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginationMeta": {
- "type": "object",
- "properties": {
- "has_more": {
- "description": "Indicates if there are more items available beyond the current result set",
- "type": "boolean",
- "example": true
- },
- "limit": {
- "description": "The maximum number of items returned in the result set",
- "type": "integer",
- "example": 100
- },
- "offset": {
- "description": "The number of items skipped before starting to collect the result set",
- "type": "integer",
- "example": 0
- },
- "total": {
- "description": "The total number of items available for the endpoint",
- "type": "integer",
- "example": 1024
- }
- }
- },
- "search.SearchRequest": {
- "type": "object",
- "properties": {
- "query": {
- "description": "The search term to look for in object names and snippets",
- "type": "string",
- "example": "test"
- },
- "sort": {
- "description": "The sorting criteria and direction for the search results",
- "allOf": [
- {
- "$ref": "#/definitions/search.SortOptions"
- }
- ]
- },
- "types": {
- "description": "The types of objects to search for, specified by unique key or ID",
- "type": "array",
- "items": {
- "type": "string"
- },
- "example": [
- "ot-note",
- "ot-page",
- "ot-678043f0cda9133be777049f",
- "bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"
- ]
- }
- }
- },
- "search.SortOptions": {
- "type": "object",
- "properties": {
- "direction": {
- "description": "The direction to sort the search results",
- "type": "string",
- "default": "desc",
- "enum": [
- "asc",
- "desc"
- ]
- },
- "timestamp": {
- "description": "The timestamp to sort the search results by",
- "type": "string",
- "default": "last_modified_date",
- "enum": [
- "created_date",
- "last_modified_date",
- "last_opened_date"
- ]
- }
- }
- },
- "space.CreateSpaceRequest": {
- "type": "object",
- "properties": {
- "name": {
- "description": "The name of the space",
- "type": "string",
- "example": "New Space"
- }
- }
- },
- "space.Member": {
- "type": "object",
- "properties": {
- "global_name": {
- "description": "The global name of the member in the network",
- "type": "string",
- "example": "john.any"
- },
- "icon": {
- "description": "The icon of the member",
- "type": "string",
- "example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"
- },
- "id": {
- "description": "The profile object id of the member",
- "type": "string",
- "example": "_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"
- },
- "identity": {
- "description": "The identity of the member in the network",
- "type": "string",
- "example": "AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"
- },
- "name": {
- "description": "The name of the member",
- "type": "string",
- "example": "John Doe"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "member"
- },
- "role": {
- "description": "The role of the member",
- "type": "string",
- "enum": [
- "Reader",
- "Writer",
- "Owner",
- "NoPermission"
- ],
- "example": "Owner"
- }
- }
- },
- "space.MemberResponse": {
- "type": "object",
- "properties": {
- "member": {
- "description": "The member",
- "allOf": [
- {
- "$ref": "#/definitions/space.Member"
- }
- ]
- }
- }
- },
- "space.Space": {
- "type": "object",
- "properties": {
- "account_space_id": {
- "description": "The id of the account space",
- "type": "string",
- "example": "bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"
- },
- "analytics_id": {
- "description": "The analytics id of the account",
- "type": "string",
- "example": "624aecdd-4797-4611-9d61-a2ae5f53cf1c"
- },
- "archive_object_id": {
- "description": "The id of the archive object",
- "type": "string",
- "example": "bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"
- },
- "device_id": {
- "description": "The id of the device",
- "type": "string",
- "example": "12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"
- },
- "gateway_url": {
- "description": "The gateway url to serve files and media",
- "type": "string",
- "example": "http://127.0.0.1:31006"
- },
- "home_object_id": {
- "description": "The id of the home object",
- "type": "string",
- "example": "bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"
- },
- "icon": {
- "description": "The icon of the space",
- "type": "string",
- "example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"
- },
- "id": {
- "description": "The id of the space",
- "type": "string",
- "example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
- },
- "local_storage_path": {
- "description": "The local storage path of the account",
- "type": "string",
- "example": "/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"
- },
- "marketplace_workspace_id": {
- "description": "The id of the marketplace workspace",
- "type": "string",
- "example": "_anytype_marketplace"
- },
- "name": {
- "description": "The name of the space",
- "type": "string",
- "example": "My Space"
- },
- "network_id": {
- "description": "The network id of the space",
- "type": "string",
- "example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "space"
- },
- "profile_object_id": {
- "description": "The id of the profile object",
- "type": "string",
- "example": "bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"
- },
- "space_view_id": {
- "description": "The id of the space view",
- "type": "string",
- "example": "bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"
- },
- "tech_space_id": {
- "description": "The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself",
- "type": "string",
- "example": "bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"
- },
- "timezone": {
- "description": "The timezone of the account",
- "type": "string",
- "example": ""
- },
- "widgets_id": {
- "description": "The id of the widgets",
- "type": "string",
- "example": "bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"
- },
- "workspace_object_id": {
- "description": "The id of the workspace object",
- "type": "string",
- "example": "bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"
- }
- }
- },
- "space.SpaceResponse": {
- "type": "object",
- "properties": {
- "space": {
- "description": "The space",
- "allOf": [
- {
- "$ref": "#/definitions/space.Space"
- }
- ]
- }
- }
- },
- "util.ForbiddenError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Forbidden"
- }
- }
- }
- }
- },
- "util.NotFoundError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Resource not found"
- }
- }
- }
- }
- },
- "util.RateLimitError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Rate limit exceeded"
- }
- }
- }
- }
- },
- "util.ServerError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Internal server error"
- }
- }
- }
- }
- },
- "util.UnauthorizedError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Unauthorized"
- }
- }
- }
- }
- },
- "util.ValidationError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Bad request"
- }
- }
- }
- }
- }
- },
- "securityDefinitions": {
- "ApiKeyAuth": {
- "type": "apiKey",
- "name": "Authorization",
- "in": "header"
- }
- }
+ "components": {"schemas":{"auth.DisplayCodeResponse":{"properties":{"challenge_id":{"description":"The challenge id associated with the displayed code and needed to solve the challenge for token","example":"67647f5ecda913e9a2e11b26","type":"string"}},"type":"object"},"auth.TokenResponse":{"properties":{"app_key":{"description":"The permanent app key","example":"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=","type":"string"},"session_token":{"description":"The ephemeral session token","example":"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII","type":"string"}},"type":"object"},"export.ObjectExportResponse":{"properties":{"path":{"description":"The path the object was exported to","example":"/path/to/export","type":"string"}},"type":"object"},"object.Block":{"properties":{"align":{"description":"The alignment of the block","enum":["AlignLeft","AlignCenter","AlignRight","AlignJustify"],"example":"AlignLeft","type":"string"},"background_color":{"description":"The background color of the block","example":"red","type":"string"},"children_ids":{"description":"The ids of the block's children","example":["['6797ce8ecda913cde14b02dc']"],"items":{"type":"string"},"type":"array","uniqueItems":false},"file":{"$ref":"#/components/schemas/object.File"},"id":{"description":"The id of the block","example":"64394517de52ad5acb89c66c","type":"string"},"relation":{"$ref":"#/components/schemas/object.Relation"},"text":{"$ref":"#/components/schemas/object.Text"},"vertical_align":{"description":"The vertical alignment of the block","enum":["VerticalAlignTop","VerticalAlignMiddle","VerticalAlignBottom"],"example":"VerticalAlignTop","type":"string"}},"type":"object"},"object.CreateObjectRequest":{"properties":{"body":{"description":"The body of the object","example":"This is the body of the object. Markdown syntax is supported here.","type":"string"},"description":{"description":"The description of the object","example":"This is a description of the object.","type":"string"},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object_type_unique_key":{"description":"The unique key of the object type","example":"ot-page","type":"string"},"source":{"description":"The source url, only applicable for bookmarks","example":"https://bookmark-source.com","type":"string"},"template_id":{"description":"The id of the template to use","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"}},"type":"object"},"object.Detail":{"properties":{"details":{"additionalProperties":{},"description":"The details","type":"object"},"id":{"description":"The id of the detail","enum":["last_modified_date","last_modified_by","created_date","created_by","last_opened_date","tags"],"example":"last_modified_date","type":"string"}},"type":"object"},"object.File":{"description":"The file of the block, if applicable","properties":{"added_at":{"description":"The added at of the file","type":"integer"},"hash":{"description":"The hash of the file","type":"string"},"mime":{"description":"The mime of the file","type":"string"},"name":{"description":"The name of the file","type":"string"},"size":{"description":"The size of the file","type":"integer"},"state":{"description":"The state of the file","type":"string"},"style":{"description":"The style of the file","type":"string"},"target_object_id":{"description":"The target object id of the file","type":"string"},"type":{"description":"The type of the file","type":"string"}},"type":"object"},"object.Object":{"description":"The object","properties":{"blocks":{"description":"The blocks of the object","items":{"$ref":"#/components/schemas/object.Block"},"type":"array","uniqueItems":false},"details":{"description":"The details of the object","items":{"$ref":"#/components/schemas/object.Detail"},"type":"array","uniqueItems":false},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"id":{"description":"The id of the object","example":"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ","type":"string"},"layout":{"description":"The layout of the object","example":"basic","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object":{"description":"The data model of the object","example":"object","type":"string"},"root_id":{"description":"The id of the object's root","example":"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u","type":"string"},"snippet":{"description":"The snippet of the object, especially important for notes as they don't have a name","example":"The beginning of the object body...","type":"string"},"space_id":{"description":"The id of the space the object is in","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"object.ObjectResponse":{"properties":{"object":{"$ref":"#/components/schemas/object.Object"}},"type":"object"},"object.Relation":{"description":"The relation of the block, if applicable","properties":{"id":{"type":"string"}},"type":"object"},"object.Template":{"description":"The template","properties":{"icon":{"description":"The icon of the template","example":"📄","type":"string"},"id":{"description":"The id of the template","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"},"name":{"description":"The name of the template","example":"My template","type":"string"},"object":{"description":"The data model of the object","example":"template","type":"string"}},"type":"object"},"object.TemplateResponse":{"properties":{"template":{"$ref":"#/components/schemas/object.Template"}},"type":"object"},"object.Text":{"description":"The text of the block, if applicable","properties":{"checked":{"description":"Whether the text is checked","example":true,"type":"boolean"},"color":{"description":"The color of the text","example":"red","type":"string"},"icon":{"description":"The icon of the text","example":"📄","type":"string"},"style":{"description":"The style of the text","enum":["Paragraph","Header1","Header2","Header3","Header4","Quote","Code","Title","Checkbox","Marked","Numbered","Toggle","Description","Callout"],"example":"Paragraph","type":"string"},"text":{"description":"The text","example":"Some text...","type":"string"}},"type":"object"},"object.Type":{"description":"The type of the object","properties":{"icon":{"description":"The icon of the type","example":"📄","type":"string"},"id":{"description":"The id of the type","example":"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu","type":"string"},"name":{"description":"The name of the type","example":"Page","type":"string"},"object":{"description":"The data model of the object","example":"type","type":"string"},"recommended_layout":{"description":"The recommended layout of the type","example":"todo","type":"string"},"unique_key":{"description":"The unique key of the type","example":"ot-page","type":"string"}},"type":"object"},"object.TypeResponse":{"properties":{"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"pagination.PaginatedResponse-object_Object":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Object"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Template":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Template"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Type":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Type"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Member":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Member"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Space":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Space"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginationMeta":{"description":"The pagination metadata for the response","properties":{"has_more":{"description":"Indicates if there are more items available beyond the current result set","example":true,"type":"boolean"},"limit":{"description":"The maximum number of items returned in the result set","example":100,"type":"integer"},"offset":{"description":"The number of items skipped before starting to collect the result set","example":0,"type":"integer"},"total":{"description":"The total number of items available for the endpoint","example":1024,"type":"integer"}},"type":"object"},"search.SearchRequest":{"properties":{"query":{"description":"The search term to look for in object names and snippets","example":"test","type":"string"},"sort":{"$ref":"#/components/schemas/search.SortOptions"},"types":{"description":"The types of objects to search for, specified by unique key or ID","example":["ot-note","ot-page","ot-678043f0cda9133be777049f","bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"],"items":{"type":"string"},"type":"array","uniqueItems":false}},"type":"object"},"search.SortOptions":{"description":"The sorting criteria and direction for the search results","properties":{"direction":{"default":"desc","description":"The direction to sort the search results","enum":["asc","desc"],"type":"string"},"timestamp":{"default":"last_modified_date","description":"The timestamp to sort the search results by","enum":["created_date","last_modified_date","last_opened_date"],"type":"string"}},"type":"object"},"space.CreateSpaceRequest":{"properties":{"name":{"description":"The name of the space","example":"New Space","type":"string"}},"type":"object"},"space.Member":{"description":"The member","properties":{"global_name":{"description":"The global name of the member in the network","example":"john.any","type":"string"},"icon":{"description":"The icon of the member","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100","type":"string"},"id":{"description":"The profile object id of the member","example":"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ","type":"string"},"identity":{"description":"The identity of the member in the network","example":"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ","type":"string"},"name":{"description":"The name of the member","example":"John Doe","type":"string"},"object":{"description":"The data model of the object","example":"member","type":"string"},"role":{"description":"The role of the member","enum":["Reader","Writer","Owner","NoPermission"],"example":"Owner","type":"string"}},"type":"object"},"space.MemberResponse":{"properties":{"member":{"$ref":"#/components/schemas/space.Member"}},"type":"object"},"space.Space":{"description":"The space","properties":{"account_space_id":{"description":"The id of the account space","example":"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1","type":"string"},"analytics_id":{"description":"The analytics id of the account","example":"624aecdd-4797-4611-9d61-a2ae5f53cf1c","type":"string"},"archive_object_id":{"description":"The id of the archive object","example":"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri","type":"string"},"device_id":{"description":"The id of the device","example":"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF","type":"string"},"gateway_url":{"description":"The gateway url to serve files and media","example":"http://127.0.0.1:31006","type":"string"},"home_object_id":{"description":"The id of the home object","example":"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya","type":"string"},"icon":{"description":"The icon of the space","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay","type":"string"},"id":{"description":"The id of the space","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"local_storage_path":{"description":"The local storage path of the account","example":"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha","type":"string"},"marketplace_workspace_id":{"description":"The id of the marketplace workspace","example":"_anytype_marketplace","type":"string"},"name":{"description":"The name of the space","example":"My Space","type":"string"},"network_id":{"description":"The network id of the space","example":"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU","type":"string"},"object":{"description":"The data model of the object","example":"space","type":"string"},"profile_object_id":{"description":"The id of the profile object","example":"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4","type":"string"},"space_view_id":{"description":"The id of the space view","example":"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy","type":"string"},"tech_space_id":{"description":"The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself","example":"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1","type":"string"},"timezone":{"description":"The timezone of the account","example":"","type":"string"},"widgets_id":{"description":"The id of the widgets","example":"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva","type":"string"},"workspace_object_id":{"description":"The id of the workspace object","example":"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y","type":"string"}},"type":"object"},"space.SpaceResponse":{"properties":{"space":{"$ref":"#/components/schemas/space.Space"}},"type":"object"},"util.ForbiddenError":{"properties":{"error":{"properties":{"message":{"example":"Forbidden","type":"string"}},"type":"object"}},"type":"object"},"util.NotFoundError":{"properties":{"error":{"properties":{"message":{"example":"Resource not found","type":"string"}},"type":"object"}},"type":"object"},"util.RateLimitError":{"properties":{"error":{"properties":{"message":{"example":"Rate limit exceeded","type":"string"}},"type":"object"}},"type":"object"},"util.ServerError":{"properties":{"error":{"properties":{"message":{"example":"Internal server error","type":"string"}},"type":"object"}},"type":"object"},"util.UnauthorizedError":{"properties":{"error":{"properties":{"message":{"example":"Unauthorized","type":"string"}},"type":"object"}},"type":"object"},"util.ValidationError":{"properties":{"error":{"properties":{"message":{"example":"Bad request","type":"string"}},"type":"object"}},"type":"object"}},"securitySchemes":{"bearerauth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"}}},
+ "info": {"contact":{"email":"support@anytype.io","name":"Anytype Support","url":"https://anytype.io/contact"},"description":"{{escape .Description}}","license":{"name":"Any Source Available License 1.0","url":"https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md"},"termsOfService":"https://anytype.io/terms_of_use","title":"{{.Title}}","version":"{{.Version}}"},
+ "externalDocs": {"description":"OpenAPI","url":"https://swagger.io/resources/open-api/"},
+ "paths": {"/auth/display_code":{"post":{"parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
+ "openapi": "3.1.0",
+ "servers": [
+ {"url":"localhost:31009/v1"}
+ ]
}`
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "1.0",
- Host: "localhost:31009",
- BasePath: "/v1",
- Schemes: []string{},
Title: "Anytype API",
Description: "This API allows interaction with Anytype resources such as spaces, objects and types.",
InfoInstanceName: "swagger",
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index f0af08881c..c79693d6bf 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -1,2159 +1,10 @@
{
- "swagger": "2.0",
- "info": {
- "description": "This API allows interaction with Anytype resources such as spaces, objects and types.",
- "title": "Anytype API",
- "termsOfService": "https://anytype.io/terms_of_use",
- "contact": {
- "name": "Anytype Support",
- "url": "https://anytype.io/contact",
- "email": "support@anytype.io"
- },
- "license": {
- "name": "Any Source Available License 1.0",
- "url": "https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md"
- },
- "version": "1.0"
- },
- "host": "localhost:31009",
- "basePath": "/v1",
- "paths": {
- "/auth/display_code": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "auth"
- ],
- "summary": "Start new challenge",
- "parameters": [
- {
- "type": "string",
- "description": "App name requesting the challenge",
- "name": "app_name",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Challenge ID",
- "schema": {
- "$ref": "#/definitions/auth.DisplayCodeResponse"
- }
- },
- "400": {
- "description": "Invalid input",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/auth/token": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "auth"
- ],
- "summary": "Retrieve token",
- "parameters": [
- {
- "type": "string",
- "description": "Challenge ID",
- "name": "challenge_id",
- "in": "query",
- "required": true
- },
- {
- "type": "string",
- "description": "4-digit code retrieved from Anytype Desktop app",
- "name": "code",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Authentication token",
- "schema": {
- "$ref": "#/definitions/auth.TokenResponse"
- }
- },
- "400": {
- "description": "Invalid input",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/search": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "search"
- ],
- "summary": "Search objects across all spaces",
- "parameters": [
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- },
- {
- "description": "Search parameters",
- "name": "request",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/search.SearchRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "List spaces",
- "parameters": [
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of spaces",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-space_Space"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "Create space",
- "parameters": [
- {
- "description": "Space to create",
- "name": "name",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/space.CreateSpaceRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Space created successfully",
- "schema": {
- "$ref": "#/definitions/space.SpaceResponse"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "423": {
- "description": "Rate limit exceeded",
- "schema": {
- "$ref": "#/definitions/util.RateLimitError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "Get space",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Space",
- "schema": {
- "$ref": "#/definitions/space.SpaceResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Space not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/members": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "List members",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of members",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-space_Member"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/members/{member_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "spaces"
- ],
- "summary": "Get member",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Member ID",
- "name": "member_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Member",
- "schema": {
- "$ref": "#/definitions/space.MemberResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Member not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/objects": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "List objects",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "Create object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "description": "Object to create",
- "name": "object",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/object.CreateObjectRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "The created object",
- "schema": {
- "$ref": "#/definitions/object.ObjectResponse"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "423": {
- "description": "Rate limit exceeded",
- "schema": {
- "$ref": "#/definitions/util.RateLimitError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/objects/{object_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "Get object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Object ID",
- "name": "object_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The requested object",
- "schema": {
- "$ref": "#/definitions/object.ObjectResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "delete": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "objects"
- ],
- "summary": "Delete object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Object ID",
- "name": "object_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The deleted object",
- "schema": {
- "$ref": "#/definitions/object.ObjectResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "403": {
- "description": "Forbidden",
- "schema": {
- "$ref": "#/definitions/util.ForbiddenError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "423": {
- "description": "Rate limit exceeded",
- "schema": {
- "$ref": "#/definitions/util.RateLimitError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/objects/{object_id}/export/{format}": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "export"
- ],
- "summary": "Export object",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Object ID",
- "name": "object_id",
- "in": "path",
- "required": true
- },
- {
- "enum": [
- "markdown",
- "protobuf"
- ],
- "type": "string",
- "description": "Export format",
- "name": "format",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "Object exported successfully",
- "schema": {
- "$ref": "#/definitions/export.ObjectExportResponse"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/search": {
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "search"
- ],
- "summary": "Search objects within a space",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- },
- {
- "description": "Search parameters",
- "name": "request",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/search.SearchRequest"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "List types",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of types",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Type"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types/{type_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "Get type",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Type ID",
- "name": "type_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The requested type",
- "schema": {
- "$ref": "#/definitions/object.TypeResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types/{type_id}/templates": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "List templates",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Type ID",
- "name": "type_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "maximum": 1000,
- "type": "integer",
- "default": 100,
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of templates",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Template"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/spaces/{space_id}/types/{type_id}/templates/{template_id}": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "types"
- ],
- "summary": "Get template",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Type ID",
- "name": "type_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "Template ID",
- "name": "template_id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "The requested template",
- "schema": {
- "$ref": "#/definitions/object.TemplateResponse"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Resource not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- },
- "/v1/spaces/{space_id}/lists/{list_id}/objects": {
- "get": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Get objects in list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "default": 0,
- "description": "The number of items to skip before starting to collect the result set",
- "name": "offset",
- "in": "query"
- },
- {
- "type": "integer",
- "description": "The number of items to return",
- "name": "limit",
- "in": "query"
- }
- ],
- "responses": {
- "200": {
- "description": "List of objects",
- "schema": {
- "$ref": "#/definitions/pagination.PaginatedResponse-object_Object"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Add objects to list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "description": "List of object IDs",
- "name": "objects",
- "in": "body",
- "required": true,
- "schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Objects added successfully",
- "schema": {
- "type": "string"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- },
- "delete": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "lists"
- ],
- "summary": "Remove objects from list",
- "parameters": [
- {
- "type": "string",
- "description": "Space ID",
- "name": "space_id",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "List ID",
- "name": "list_id",
- "in": "path",
- "required": true
- },
- {
- "description": "List of object IDs",
- "name": "objects",
- "in": "body",
- "required": true,
- "schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Objects removed successfully",
- "schema": {
- "type": "string"
- }
- },
- "400": {
- "description": "Bad request",
- "schema": {
- "$ref": "#/definitions/util.ValidationError"
- }
- },
- "401": {
- "description": "Unauthorized",
- "schema": {
- "$ref": "#/definitions/util.UnauthorizedError"
- }
- },
- "404": {
- "description": "Not found",
- "schema": {
- "$ref": "#/definitions/util.NotFoundError"
- }
- },
- "500": {
- "description": "Internal server error",
- "schema": {
- "$ref": "#/definitions/util.ServerError"
- }
- }
- }
- }
- }
- },
- "definitions": {
- "auth.DisplayCodeResponse": {
- "type": "object",
- "properties": {
- "challenge_id": {
- "description": "The challenge id associated with the displayed code and needed to solve the challenge for token",
- "type": "string",
- "example": "67647f5ecda913e9a2e11b26"
- }
- }
- },
- "auth.TokenResponse": {
- "type": "object",
- "properties": {
- "app_key": {
- "description": "The permanent app key",
- "type": "string",
- "example": "zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="
- },
- "session_token": {
- "description": "The ephemeral session token",
- "type": "string",
- "example": "eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"
- }
- }
- },
- "export.ObjectExportResponse": {
- "type": "object",
- "properties": {
- "path": {
- "description": "The path the object was exported to",
- "type": "string",
- "example": "/path/to/export"
- }
- }
- },
- "object.Block": {
- "type": "object",
- "properties": {
- "align": {
- "description": "The alignment of the block",
- "type": "string",
- "enum": [
- "AlignLeft",
- "AlignCenter",
- "AlignRight",
- "AlignJustify"
- ],
- "example": "AlignLeft"
- },
- "background_color": {
- "description": "The background color of the block",
- "type": "string",
- "example": "red"
- },
- "children_ids": {
- "description": "The ids of the block's children",
- "type": "array",
- "items": {
- "type": "string"
- },
- "example": [
- "['6797ce8ecda913cde14b02dc']"
- ]
- },
- "file": {
- "description": "The file of the block, if applicable",
- "allOf": [
- {
- "$ref": "#/definitions/object.File"
- }
- ]
- },
- "id": {
- "description": "The id of the block",
- "type": "string",
- "example": "64394517de52ad5acb89c66c"
- },
- "relation": {
- "description": "The relation of the block, if applicable",
- "allOf": [
- {
- "$ref": "#/definitions/object.Relation"
- }
- ]
- },
- "text": {
- "description": "The text of the block, if applicable",
- "allOf": [
- {
- "$ref": "#/definitions/object.Text"
- }
- ]
- },
- "vertical_align": {
- "description": "The vertical alignment of the block",
- "type": "string",
- "enum": [
- "VerticalAlignTop",
- "VerticalAlignMiddle",
- "VerticalAlignBottom"
- ],
- "example": "VerticalAlignTop"
- }
- }
- },
- "object.CreateObjectRequest": {
- "type": "object",
- "properties": {
- "body": {
- "description": "The body of the object",
- "type": "string",
- "example": "This is the body of the object. Markdown syntax is supported here."
- },
- "description": {
- "description": "The description of the object",
- "type": "string",
- "example": "This is a description of the object."
- },
- "icon": {
- "description": "The icon of the object",
- "type": "string",
- "example": "📄"
- },
- "name": {
- "description": "The name of the object",
- "type": "string",
- "example": "My object"
- },
- "object_type_unique_key": {
- "description": "The unique key of the object type",
- "type": "string",
- "example": "ot-page"
- },
- "source": {
- "description": "The source url, only applicable for bookmarks",
- "type": "string",
- "example": "https://bookmark-source.com"
- },
- "template_id": {
- "description": "The id of the template to use",
- "type": "string",
- "example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
- }
- }
- },
- "object.Detail": {
- "type": "object",
- "properties": {
- "details": {
- "description": "The details",
- "type": "object",
- "additionalProperties": true
- },
- "id": {
- "description": "The id of the detail",
- "type": "string",
- "enum": [
- "last_modified_date",
- "last_modified_by",
- "created_date",
- "created_by",
- "last_opened_date",
- "tags"
- ],
- "example": "last_modified_date"
- }
- }
- },
- "object.File": {
- "type": "object",
- "properties": {
- "added_at": {
- "description": "The added at of the file",
- "type": "integer"
- },
- "hash": {
- "description": "The hash of the file",
- "type": "string"
- },
- "mime": {
- "description": "The mime of the file",
- "type": "string"
- },
- "name": {
- "description": "The name of the file",
- "type": "string"
- },
- "size": {
- "description": "The size of the file",
- "type": "integer"
- },
- "state": {
- "description": "The state of the file",
- "type": "string"
- },
- "style": {
- "description": "The style of the file",
- "type": "string"
- },
- "target_object_id": {
- "description": "The target object id of the file",
- "type": "string"
- },
- "type": {
- "description": "The type of the file",
- "type": "string"
- }
- }
- },
- "object.Object": {
- "type": "object",
- "properties": {
- "blocks": {
- "description": "The blocks of the object",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Block"
- }
- },
- "details": {
- "description": "The details of the object",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Detail"
- }
- },
- "icon": {
- "description": "The icon of the object",
- "type": "string",
- "example": "📄"
- },
- "id": {
- "description": "The id of the object",
- "type": "string",
- "example": "bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"
- },
- "layout": {
- "description": "The layout of the object",
- "type": "string",
- "example": "basic"
- },
- "name": {
- "description": "The name of the object",
- "type": "string",
- "example": "My object"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "object"
- },
- "root_id": {
- "description": "The id of the object's root",
- "type": "string",
- "example": "bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"
- },
- "snippet": {
- "description": "The snippet of the object, especially important for notes as they don't have a name",
- "type": "string",
- "example": "The beginning of the object body..."
- },
- "space_id": {
- "description": "The id of the space the object is in",
- "type": "string",
- "example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
- },
- "type": {
- "description": "The type of the object",
- "allOf": [
- {
- "$ref": "#/definitions/object.Type"
- }
- ]
- }
- }
- },
- "object.ObjectResponse": {
- "type": "object",
- "properties": {
- "object": {
- "description": "The object",
- "allOf": [
- {
- "$ref": "#/definitions/object.Object"
- }
- ]
- }
- }
- },
- "object.Relation": {
- "type": "object",
- "properties": {
- "id": {
- "type": "string"
- }
- }
- },
- "object.Template": {
- "type": "object",
- "properties": {
- "icon": {
- "description": "The icon of the template",
- "type": "string",
- "example": "📄"
- },
- "id": {
- "description": "The id of the template",
- "type": "string",
- "example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
- },
- "name": {
- "description": "The name of the template",
- "type": "string",
- "example": "My template"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "template"
- }
- }
- },
- "object.TemplateResponse": {
- "type": "object",
- "properties": {
- "template": {
- "description": "The template",
- "allOf": [
- {
- "$ref": "#/definitions/object.Template"
- }
- ]
- }
- }
- },
- "object.Text": {
- "type": "object",
- "properties": {
- "checked": {
- "description": "Whether the text is checked",
- "type": "boolean",
- "example": true
- },
- "color": {
- "description": "The color of the text",
- "type": "string",
- "example": "red"
- },
- "icon": {
- "description": "The icon of the text",
- "type": "string",
- "example": "📄"
- },
- "style": {
- "description": "The style of the text",
- "type": "string",
- "enum": [
- "Paragraph",
- "Header1",
- "Header2",
- "Header3",
- "Header4",
- "Quote",
- "Code",
- "Title",
- "Checkbox",
- "Marked",
- "Numbered",
- "Toggle",
- "Description",
- "Callout"
- ],
- "example": "Paragraph"
- },
- "text": {
- "description": "The text",
- "type": "string",
- "example": "Some text..."
- }
- }
- },
- "object.Type": {
- "type": "object",
- "properties": {
- "icon": {
- "description": "The icon of the type",
- "type": "string",
- "example": "📄"
- },
- "id": {
- "description": "The id of the type",
- "type": "string",
- "example": "bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"
- },
- "name": {
- "description": "The name of the type",
- "type": "string",
- "example": "Page"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "type"
- },
- "recommended_layout": {
- "description": "The recommended layout of the type",
- "type": "string",
- "example": "todo"
- },
- "unique_key": {
- "description": "The unique key of the type",
- "type": "string",
- "example": "ot-page"
- }
- }
- },
- "object.TypeResponse": {
- "type": "object",
- "properties": {
- "type": {
- "description": "The type",
- "allOf": [
- {
- "$ref": "#/definitions/object.Type"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-object_Object": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Object"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-object_Template": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Template"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-object_Type": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/object.Type"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-space_Member": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/space.Member"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginatedResponse-space_Space": {
- "type": "object",
- "properties": {
- "data": {
- "description": "The list of items in the current result set",
- "type": "array",
- "items": {
- "$ref": "#/definitions/space.Space"
- }
- },
- "pagination": {
- "description": "The pagination metadata for the response",
- "allOf": [
- {
- "$ref": "#/definitions/pagination.PaginationMeta"
- }
- ]
- }
- }
- },
- "pagination.PaginationMeta": {
- "type": "object",
- "properties": {
- "has_more": {
- "description": "Indicates if there are more items available beyond the current result set",
- "type": "boolean",
- "example": true
- },
- "limit": {
- "description": "The maximum number of items returned in the result set",
- "type": "integer",
- "example": 100
- },
- "offset": {
- "description": "The number of items skipped before starting to collect the result set",
- "type": "integer",
- "example": 0
- },
- "total": {
- "description": "The total number of items available for the endpoint",
- "type": "integer",
- "example": 1024
- }
- }
- },
- "search.SearchRequest": {
- "type": "object",
- "properties": {
- "query": {
- "description": "The search term to look for in object names and snippets",
- "type": "string",
- "example": "test"
- },
- "sort": {
- "description": "The sorting criteria and direction for the search results",
- "allOf": [
- {
- "$ref": "#/definitions/search.SortOptions"
- }
- ]
- },
- "types": {
- "description": "The types of objects to search for, specified by unique key or ID",
- "type": "array",
- "items": {
- "type": "string"
- },
- "example": [
- "ot-note",
- "ot-page",
- "ot-678043f0cda9133be777049f",
- "bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"
- ]
- }
- }
- },
- "search.SortOptions": {
- "type": "object",
- "properties": {
- "direction": {
- "description": "The direction to sort the search results",
- "type": "string",
- "default": "desc",
- "enum": [
- "asc",
- "desc"
- ]
- },
- "timestamp": {
- "description": "The timestamp to sort the search results by",
- "type": "string",
- "default": "last_modified_date",
- "enum": [
- "created_date",
- "last_modified_date",
- "last_opened_date"
- ]
- }
- }
- },
- "space.CreateSpaceRequest": {
- "type": "object",
- "properties": {
- "name": {
- "description": "The name of the space",
- "type": "string",
- "example": "New Space"
- }
- }
- },
- "space.Member": {
- "type": "object",
- "properties": {
- "global_name": {
- "description": "The global name of the member in the network",
- "type": "string",
- "example": "john.any"
- },
- "icon": {
- "description": "The icon of the member",
- "type": "string",
- "example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"
- },
- "id": {
- "description": "The profile object id of the member",
- "type": "string",
- "example": "_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"
- },
- "identity": {
- "description": "The identity of the member in the network",
- "type": "string",
- "example": "AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"
- },
- "name": {
- "description": "The name of the member",
- "type": "string",
- "example": "John Doe"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "member"
- },
- "role": {
- "description": "The role of the member",
- "type": "string",
- "enum": [
- "Reader",
- "Writer",
- "Owner",
- "NoPermission"
- ],
- "example": "Owner"
- }
- }
- },
- "space.MemberResponse": {
- "type": "object",
- "properties": {
- "member": {
- "description": "The member",
- "allOf": [
- {
- "$ref": "#/definitions/space.Member"
- }
- ]
- }
- }
- },
- "space.Space": {
- "type": "object",
- "properties": {
- "account_space_id": {
- "description": "The id of the account space",
- "type": "string",
- "example": "bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"
- },
- "analytics_id": {
- "description": "The analytics id of the account",
- "type": "string",
- "example": "624aecdd-4797-4611-9d61-a2ae5f53cf1c"
- },
- "archive_object_id": {
- "description": "The id of the archive object",
- "type": "string",
- "example": "bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"
- },
- "device_id": {
- "description": "The id of the device",
- "type": "string",
- "example": "12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"
- },
- "gateway_url": {
- "description": "The gateway url to serve files and media",
- "type": "string",
- "example": "http://127.0.0.1:31006"
- },
- "home_object_id": {
- "description": "The id of the home object",
- "type": "string",
- "example": "bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"
- },
- "icon": {
- "description": "The icon of the space",
- "type": "string",
- "example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"
- },
- "id": {
- "description": "The id of the space",
- "type": "string",
- "example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
- },
- "local_storage_path": {
- "description": "The local storage path of the account",
- "type": "string",
- "example": "/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"
- },
- "marketplace_workspace_id": {
- "description": "The id of the marketplace workspace",
- "type": "string",
- "example": "_anytype_marketplace"
- },
- "name": {
- "description": "The name of the space",
- "type": "string",
- "example": "My Space"
- },
- "network_id": {
- "description": "The network id of the space",
- "type": "string",
- "example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
- },
- "object": {
- "description": "The data model of the object",
- "type": "string",
- "example": "space"
- },
- "profile_object_id": {
- "description": "The id of the profile object",
- "type": "string",
- "example": "bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"
- },
- "space_view_id": {
- "description": "The id of the space view",
- "type": "string",
- "example": "bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"
- },
- "tech_space_id": {
- "description": "The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself",
- "type": "string",
- "example": "bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"
- },
- "timezone": {
- "description": "The timezone of the account",
- "type": "string",
- "example": ""
- },
- "widgets_id": {
- "description": "The id of the widgets",
- "type": "string",
- "example": "bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"
- },
- "workspace_object_id": {
- "description": "The id of the workspace object",
- "type": "string",
- "example": "bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"
- }
- }
- },
- "space.SpaceResponse": {
- "type": "object",
- "properties": {
- "space": {
- "description": "The space",
- "allOf": [
- {
- "$ref": "#/definitions/space.Space"
- }
- ]
- }
- }
- },
- "util.ForbiddenError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Forbidden"
- }
- }
- }
- }
- },
- "util.NotFoundError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Resource not found"
- }
- }
- }
- }
- },
- "util.RateLimitError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Rate limit exceeded"
- }
- }
- }
- }
- },
- "util.ServerError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Internal server error"
- }
- }
- }
- }
- },
- "util.UnauthorizedError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Unauthorized"
- }
- }
- }
- }
- },
- "util.ValidationError": {
- "type": "object",
- "properties": {
- "error": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Bad request"
- }
- }
- }
- }
- }
- },
- "securityDefinitions": {
- "ApiKeyAuth": {
- "type": "apiKey",
- "name": "Authorization",
- "in": "header"
- }
- }
+ "components": {"schemas":{"auth.DisplayCodeResponse":{"properties":{"challenge_id":{"description":"The challenge id associated with the displayed code and needed to solve the challenge for token","example":"67647f5ecda913e9a2e11b26","type":"string"}},"type":"object"},"auth.TokenResponse":{"properties":{"app_key":{"description":"The permanent app key","example":"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=","type":"string"},"session_token":{"description":"The ephemeral session token","example":"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII","type":"string"}},"type":"object"},"export.ObjectExportResponse":{"properties":{"path":{"description":"The path the object was exported to","example":"/path/to/export","type":"string"}},"type":"object"},"object.Block":{"properties":{"align":{"description":"The alignment of the block","enum":["AlignLeft","AlignCenter","AlignRight","AlignJustify"],"example":"AlignLeft","type":"string"},"background_color":{"description":"The background color of the block","example":"red","type":"string"},"children_ids":{"description":"The ids of the block's children","example":["['6797ce8ecda913cde14b02dc']"],"items":{"type":"string"},"type":"array","uniqueItems":false},"file":{"$ref":"#/components/schemas/object.File"},"id":{"description":"The id of the block","example":"64394517de52ad5acb89c66c","type":"string"},"relation":{"$ref":"#/components/schemas/object.Relation"},"text":{"$ref":"#/components/schemas/object.Text"},"vertical_align":{"description":"The vertical alignment of the block","enum":["VerticalAlignTop","VerticalAlignMiddle","VerticalAlignBottom"],"example":"VerticalAlignTop","type":"string"}},"type":"object"},"object.CreateObjectRequest":{"properties":{"body":{"description":"The body of the object","example":"This is the body of the object. Markdown syntax is supported here.","type":"string"},"description":{"description":"The description of the object","example":"This is a description of the object.","type":"string"},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object_type_unique_key":{"description":"The unique key of the object type","example":"ot-page","type":"string"},"source":{"description":"The source url, only applicable for bookmarks","example":"https://bookmark-source.com","type":"string"},"template_id":{"description":"The id of the template to use","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"}},"type":"object"},"object.Detail":{"properties":{"details":{"additionalProperties":{},"description":"The details","type":"object"},"id":{"description":"The id of the detail","enum":["last_modified_date","last_modified_by","created_date","created_by","last_opened_date","tags"],"example":"last_modified_date","type":"string"}},"type":"object"},"object.File":{"description":"The file of the block, if applicable","properties":{"added_at":{"description":"The added at of the file","type":"integer"},"hash":{"description":"The hash of the file","type":"string"},"mime":{"description":"The mime of the file","type":"string"},"name":{"description":"The name of the file","type":"string"},"size":{"description":"The size of the file","type":"integer"},"state":{"description":"The state of the file","type":"string"},"style":{"description":"The style of the file","type":"string"},"target_object_id":{"description":"The target object id of the file","type":"string"},"type":{"description":"The type of the file","type":"string"}},"type":"object"},"object.Object":{"description":"The object","properties":{"blocks":{"description":"The blocks of the object","items":{"$ref":"#/components/schemas/object.Block"},"type":"array","uniqueItems":false},"details":{"description":"The details of the object","items":{"$ref":"#/components/schemas/object.Detail"},"type":"array","uniqueItems":false},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"id":{"description":"The id of the object","example":"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ","type":"string"},"layout":{"description":"The layout of the object","example":"basic","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object":{"description":"The data model of the object","example":"object","type":"string"},"root_id":{"description":"The id of the object's root","example":"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u","type":"string"},"snippet":{"description":"The snippet of the object, especially important for notes as they don't have a name","example":"The beginning of the object body...","type":"string"},"space_id":{"description":"The id of the space the object is in","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"object.ObjectResponse":{"properties":{"object":{"$ref":"#/components/schemas/object.Object"}},"type":"object"},"object.Relation":{"description":"The relation of the block, if applicable","properties":{"id":{"type":"string"}},"type":"object"},"object.Template":{"description":"The template","properties":{"icon":{"description":"The icon of the template","example":"📄","type":"string"},"id":{"description":"The id of the template","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"},"name":{"description":"The name of the template","example":"My template","type":"string"},"object":{"description":"The data model of the object","example":"template","type":"string"}},"type":"object"},"object.TemplateResponse":{"properties":{"template":{"$ref":"#/components/schemas/object.Template"}},"type":"object"},"object.Text":{"description":"The text of the block, if applicable","properties":{"checked":{"description":"Whether the text is checked","example":true,"type":"boolean"},"color":{"description":"The color of the text","example":"red","type":"string"},"icon":{"description":"The icon of the text","example":"📄","type":"string"},"style":{"description":"The style of the text","enum":["Paragraph","Header1","Header2","Header3","Header4","Quote","Code","Title","Checkbox","Marked","Numbered","Toggle","Description","Callout"],"example":"Paragraph","type":"string"},"text":{"description":"The text","example":"Some text...","type":"string"}},"type":"object"},"object.Type":{"description":"The type of the object","properties":{"icon":{"description":"The icon of the type","example":"📄","type":"string"},"id":{"description":"The id of the type","example":"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu","type":"string"},"name":{"description":"The name of the type","example":"Page","type":"string"},"object":{"description":"The data model of the object","example":"type","type":"string"},"recommended_layout":{"description":"The recommended layout of the type","example":"todo","type":"string"},"unique_key":{"description":"The unique key of the type","example":"ot-page","type":"string"}},"type":"object"},"object.TypeResponse":{"properties":{"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"pagination.PaginatedResponse-object_Object":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Object"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Template":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Template"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Type":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Type"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Member":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Member"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Space":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Space"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginationMeta":{"description":"The pagination metadata for the response","properties":{"has_more":{"description":"Indicates if there are more items available beyond the current result set","example":true,"type":"boolean"},"limit":{"description":"The maximum number of items returned in the result set","example":100,"type":"integer"},"offset":{"description":"The number of items skipped before starting to collect the result set","example":0,"type":"integer"},"total":{"description":"The total number of items available for the endpoint","example":1024,"type":"integer"}},"type":"object"},"search.SearchRequest":{"properties":{"query":{"description":"The search term to look for in object names and snippets","example":"test","type":"string"},"sort":{"$ref":"#/components/schemas/search.SortOptions"},"types":{"description":"The types of objects to search for, specified by unique key or ID","example":["ot-note","ot-page","ot-678043f0cda9133be777049f","bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"],"items":{"type":"string"},"type":"array","uniqueItems":false}},"type":"object"},"search.SortOptions":{"description":"The sorting criteria and direction for the search results","properties":{"direction":{"default":"desc","description":"The direction to sort the search results","enum":["asc","desc"],"type":"string"},"timestamp":{"default":"last_modified_date","description":"The timestamp to sort the search results by","enum":["created_date","last_modified_date","last_opened_date"],"type":"string"}},"type":"object"},"space.CreateSpaceRequest":{"properties":{"name":{"description":"The name of the space","example":"New Space","type":"string"}},"type":"object"},"space.Member":{"description":"The member","properties":{"global_name":{"description":"The global name of the member in the network","example":"john.any","type":"string"},"icon":{"description":"The icon of the member","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100","type":"string"},"id":{"description":"The profile object id of the member","example":"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ","type":"string"},"identity":{"description":"The identity of the member in the network","example":"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ","type":"string"},"name":{"description":"The name of the member","example":"John Doe","type":"string"},"object":{"description":"The data model of the object","example":"member","type":"string"},"role":{"description":"The role of the member","enum":["Reader","Writer","Owner","NoPermission"],"example":"Owner","type":"string"}},"type":"object"},"space.MemberResponse":{"properties":{"member":{"$ref":"#/components/schemas/space.Member"}},"type":"object"},"space.Space":{"description":"The space","properties":{"account_space_id":{"description":"The id of the account space","example":"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1","type":"string"},"analytics_id":{"description":"The analytics id of the account","example":"624aecdd-4797-4611-9d61-a2ae5f53cf1c","type":"string"},"archive_object_id":{"description":"The id of the archive object","example":"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri","type":"string"},"device_id":{"description":"The id of the device","example":"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF","type":"string"},"gateway_url":{"description":"The gateway url to serve files and media","example":"http://127.0.0.1:31006","type":"string"},"home_object_id":{"description":"The id of the home object","example":"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya","type":"string"},"icon":{"description":"The icon of the space","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay","type":"string"},"id":{"description":"The id of the space","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"local_storage_path":{"description":"The local storage path of the account","example":"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha","type":"string"},"marketplace_workspace_id":{"description":"The id of the marketplace workspace","example":"_anytype_marketplace","type":"string"},"name":{"description":"The name of the space","example":"My Space","type":"string"},"network_id":{"description":"The network id of the space","example":"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU","type":"string"},"object":{"description":"The data model of the object","example":"space","type":"string"},"profile_object_id":{"description":"The id of the profile object","example":"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4","type":"string"},"space_view_id":{"description":"The id of the space view","example":"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy","type":"string"},"tech_space_id":{"description":"The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself","example":"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1","type":"string"},"timezone":{"description":"The timezone of the account","example":"","type":"string"},"widgets_id":{"description":"The id of the widgets","example":"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva","type":"string"},"workspace_object_id":{"description":"The id of the workspace object","example":"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y","type":"string"}},"type":"object"},"space.SpaceResponse":{"properties":{"space":{"$ref":"#/components/schemas/space.Space"}},"type":"object"},"util.ForbiddenError":{"properties":{"error":{"properties":{"message":{"example":"Forbidden","type":"string"}},"type":"object"}},"type":"object"},"util.NotFoundError":{"properties":{"error":{"properties":{"message":{"example":"Resource not found","type":"string"}},"type":"object"}},"type":"object"},"util.RateLimitError":{"properties":{"error":{"properties":{"message":{"example":"Rate limit exceeded","type":"string"}},"type":"object"}},"type":"object"},"util.ServerError":{"properties":{"error":{"properties":{"message":{"example":"Internal server error","type":"string"}},"type":"object"}},"type":"object"},"util.UnauthorizedError":{"properties":{"error":{"properties":{"message":{"example":"Unauthorized","type":"string"}},"type":"object"}},"type":"object"},"util.ValidationError":{"properties":{"error":{"properties":{"message":{"example":"Bad request","type":"string"}},"type":"object"}},"type":"object"}},"securitySchemes":{"bearerauth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"}}},
+ "info": {"contact":{"email":"support@anytype.io","name":"Anytype Support","url":"https://anytype.io/contact"},"description":"This API allows interaction with Anytype resources such as spaces, objects and types.","license":{"name":"Any Source Available License 1.0","url":"https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md"},"termsOfService":"https://anytype.io/terms_of_use","title":"Anytype API","version":"1.0"},
+ "externalDocs": {"description":"OpenAPI","url":"https://swagger.io/resources/open-api/"},
+ "paths": {"/auth/display_code":{"post":{"parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
+ "openapi": "3.1.0",
+ "servers": [
+ {"url":"localhost:31009/v1"}
+ ]
}
\ No newline at end of file
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index c4dfe63d13..deb31aec21 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -1,630 +1,626 @@
-basePath: /v1
-definitions:
- auth.DisplayCodeResponse:
- properties:
- challenge_id:
- description: The challenge id associated with the displayed code and needed
- to solve the challenge for token
- example: 67647f5ecda913e9a2e11b26
- type: string
- type: object
- auth.TokenResponse:
- properties:
- app_key:
- description: The permanent app key
- example: zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=
- type: string
- session_token:
- description: The ephemeral session token
- example: eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII
- type: string
- type: object
- export.ObjectExportResponse:
- properties:
- path:
- description: The path the object was exported to
- example: /path/to/export
- type: string
- type: object
- object.Block:
- properties:
- align:
- description: The alignment of the block
- enum:
- - AlignLeft
- - AlignCenter
- - AlignRight
- - AlignJustify
- example: AlignLeft
- type: string
- background_color:
- description: The background color of the block
- example: red
- type: string
- children_ids:
- description: The ids of the block's children
- example:
- - '[''6797ce8ecda913cde14b02dc'']'
- items:
- type: string
- type: array
- file:
- allOf:
- - $ref: '#/definitions/object.File'
- description: The file of the block, if applicable
- id:
- description: The id of the block
- example: 64394517de52ad5acb89c66c
- type: string
- relation:
- allOf:
- - $ref: '#/definitions/object.Relation'
- description: The relation of the block, if applicable
- text:
- allOf:
- - $ref: '#/definitions/object.Text'
- description: The text of the block, if applicable
- vertical_align:
- description: The vertical alignment of the block
- enum:
- - VerticalAlignTop
- - VerticalAlignMiddle
- - VerticalAlignBottom
- example: VerticalAlignTop
- type: string
- type: object
- object.CreateObjectRequest:
- properties:
- body:
- description: The body of the object
- example: This is the body of the object. Markdown syntax is supported here.
- type: string
- description:
- description: The description of the object
- example: This is a description of the object.
- type: string
- icon:
- description: The icon of the object
- example: "\U0001F4C4"
- type: string
- name:
- description: The name of the object
- example: My object
- type: string
- object_type_unique_key:
- description: The unique key of the object type
- example: ot-page
- type: string
- source:
- description: The source url, only applicable for bookmarks
- example: https://bookmark-source.com
- type: string
- template_id:
- description: The id of the template to use
- example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
- type: string
- type: object
- object.Detail:
- properties:
- details:
- additionalProperties: true
- description: The details
- type: object
- id:
- description: The id of the detail
- enum:
- - last_modified_date
- - last_modified_by
- - created_date
- - created_by
- - last_opened_date
- - tags
- example: last_modified_date
- type: string
- type: object
- object.File:
- properties:
- added_at:
- description: The added at of the file
- type: integer
- hash:
- description: The hash of the file
- type: string
- mime:
- description: The mime of the file
- type: string
- name:
- description: The name of the file
- type: string
- size:
- description: The size of the file
- type: integer
- state:
- description: The state of the file
- type: string
- style:
- description: The style of the file
- type: string
- target_object_id:
- description: The target object id of the file
- type: string
- type:
- description: The type of the file
- type: string
- type: object
- object.Object:
- properties:
- blocks:
- description: The blocks of the object
- items:
- $ref: '#/definitions/object.Block'
- type: array
- details:
- description: The details of the object
- items:
- $ref: '#/definitions/object.Detail'
- type: array
- icon:
- description: The icon of the object
- example: "\U0001F4C4"
- type: string
- id:
- description: The id of the object
- example: bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ
- type: string
- layout:
- description: The layout of the object
- example: basic
- type: string
- name:
- description: The name of the object
- example: My object
- type: string
- object:
- description: The data model of the object
- example: object
- type: string
- root_id:
- description: The id of the object's root
- example: bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u
- type: string
- snippet:
- description: The snippet of the object, especially important for notes as
- they don't have a name
- example: The beginning of the object body...
- type: string
- space_id:
- description: The id of the space the object is in
- example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
- type: string
- type:
- allOf:
- - $ref: '#/definitions/object.Type'
- description: The type of the object
- type: object
- object.ObjectResponse:
- properties:
- object:
- allOf:
- - $ref: '#/definitions/object.Object'
- description: The object
- type: object
- object.Relation:
- properties:
- id:
- type: string
- type: object
- object.Template:
- properties:
- icon:
- description: The icon of the template
- example: "\U0001F4C4"
- type: string
- id:
- description: The id of the template
- example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
- type: string
- name:
- description: The name of the template
- example: My template
- type: string
- object:
- description: The data model of the object
- example: template
- type: string
- type: object
- object.TemplateResponse:
- properties:
- template:
- allOf:
- - $ref: '#/definitions/object.Template'
- description: The template
- type: object
- object.Text:
- properties:
- checked:
- description: Whether the text is checked
- example: true
- type: boolean
- color:
- description: The color of the text
- example: red
- type: string
- icon:
- description: The icon of the text
- example: "\U0001F4C4"
- type: string
- style:
- description: The style of the text
- enum:
- - Paragraph
- - Header1
- - Header2
- - Header3
- - Header4
- - Quote
- - Code
- - Title
- - Checkbox
- - Marked
- - Numbered
- - Toggle
- - Description
- - Callout
- example: Paragraph
- type: string
- text:
- description: The text
- example: Some text...
- type: string
- type: object
- object.Type:
- properties:
- icon:
- description: The icon of the type
- example: "\U0001F4C4"
- type: string
- id:
- description: The id of the type
- example: bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu
- type: string
- name:
- description: The name of the type
- example: Page
- type: string
- object:
- description: The data model of the object
- example: type
- type: string
- recommended_layout:
- description: The recommended layout of the type
- example: todo
- type: string
- unique_key:
- description: The unique key of the type
- example: ot-page
- type: string
- type: object
- object.TypeResponse:
- properties:
- type:
- allOf:
- - $ref: '#/definitions/object.Type'
- description: The type
- type: object
- pagination.PaginatedResponse-object_Object:
- properties:
- data:
- description: The list of items in the current result set
- items:
- $ref: '#/definitions/object.Object'
- type: array
- pagination:
- allOf:
- - $ref: '#/definitions/pagination.PaginationMeta'
- description: The pagination metadata for the response
- type: object
- pagination.PaginatedResponse-object_Template:
- properties:
- data:
- description: The list of items in the current result set
- items:
- $ref: '#/definitions/object.Template'
- type: array
- pagination:
- allOf:
- - $ref: '#/definitions/pagination.PaginationMeta'
- description: The pagination metadata for the response
- type: object
- pagination.PaginatedResponse-object_Type:
- properties:
- data:
- description: The list of items in the current result set
- items:
- $ref: '#/definitions/object.Type'
- type: array
- pagination:
- allOf:
- - $ref: '#/definitions/pagination.PaginationMeta'
- description: The pagination metadata for the response
- type: object
- pagination.PaginatedResponse-space_Member:
- properties:
- data:
- description: The list of items in the current result set
- items:
- $ref: '#/definitions/space.Member'
- type: array
- pagination:
- allOf:
- - $ref: '#/definitions/pagination.PaginationMeta'
- description: The pagination metadata for the response
- type: object
- pagination.PaginatedResponse-space_Space:
- properties:
- data:
- description: The list of items in the current result set
- items:
- $ref: '#/definitions/space.Space'
- type: array
- pagination:
- allOf:
- - $ref: '#/definitions/pagination.PaginationMeta'
- description: The pagination metadata for the response
- type: object
- pagination.PaginationMeta:
- properties:
- has_more:
- description: Indicates if there are more items available beyond the current
- result set
- example: true
- type: boolean
- limit:
- description: The maximum number of items returned in the result set
- example: 100
- type: integer
- offset:
- description: The number of items skipped before starting to collect the result
- set
- example: 0
- type: integer
- total:
- description: The total number of items available for the endpoint
- example: 1024
- type: integer
- type: object
- search.SearchRequest:
- properties:
- query:
- description: The search term to look for in object names and snippets
- example: test
- type: string
- sort:
- allOf:
- - $ref: '#/definitions/search.SortOptions'
- description: The sorting criteria and direction for the search results
- types:
- description: The types of objects to search for, specified by unique key or
- ID
- example:
- - ot-note
- - ot-page
- - ot-678043f0cda9133be777049f
- - bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q
- items:
- type: string
- type: array
- type: object
- search.SortOptions:
- properties:
- direction:
- default: desc
- description: The direction to sort the search results
- enum:
- - asc
- - desc
- type: string
- timestamp:
- default: last_modified_date
- description: The timestamp to sort the search results by
- enum:
- - created_date
- - last_modified_date
- - last_opened_date
- type: string
- type: object
- space.CreateSpaceRequest:
- properties:
- name:
- description: The name of the space
- example: New Space
- type: string
- type: object
- space.Member:
- properties:
- global_name:
- description: The global name of the member in the network
- example: john.any
- type: string
- icon:
- description: The icon of the member
- example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100
- type: string
- id:
- description: The profile object id of the member
- example: _participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ
- type: string
- identity:
- description: The identity of the member in the network
- example: AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ
- type: string
- name:
- description: The name of the member
- example: John Doe
- type: string
- object:
- description: The data model of the object
- example: member
- type: string
- role:
- description: The role of the member
- enum:
- - Reader
- - Writer
- - Owner
- - NoPermission
- example: Owner
- type: string
- type: object
- space.MemberResponse:
- properties:
- member:
- allOf:
- - $ref: '#/definitions/space.Member'
- description: The member
- type: object
- space.Space:
- properties:
- account_space_id:
- description: The id of the account space
- example: bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1
- type: string
- analytics_id:
- description: The analytics id of the account
- example: 624aecdd-4797-4611-9d61-a2ae5f53cf1c
- type: string
- archive_object_id:
- description: The id of the archive object
- example: bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri
- type: string
- device_id:
- description: The id of the device
- example: 12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF
- type: string
- gateway_url:
- description: The gateway url to serve files and media
- example: http://127.0.0.1:31006
- type: string
- home_object_id:
- description: The id of the home object
- example: bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya
- type: string
- icon:
- description: The icon of the space
- example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay
- type: string
- id:
- description: The id of the space
- example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
- type: string
- local_storage_path:
- description: The local storage path of the account
- example: /Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha
- type: string
- marketplace_workspace_id:
- description: The id of the marketplace workspace
- example: _anytype_marketplace
- type: string
- name:
- description: The name of the space
- example: My Space
- type: string
- network_id:
- description: The network id of the space
- example: N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU
- type: string
- object:
- description: The data model of the object
- example: space
- type: string
- profile_object_id:
- description: The id of the profile object
- example: bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4
- type: string
- space_view_id:
- description: The id of the space view
- example: bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy
- type: string
- tech_space_id:
- description: The id of tech space, where objects outside of user's actual
- spaces are stored, e.g. spaces itself
- example: bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1
- type: string
- timezone:
- description: The timezone of the account
- example: ""
- type: string
- widgets_id:
- description: The id of the widgets
- example: bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva
- type: string
- workspace_object_id:
- description: The id of the workspace object
- example: bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y
- type: string
- type: object
- space.SpaceResponse:
- properties:
- space:
- allOf:
- - $ref: '#/definitions/space.Space'
- description: The space
- type: object
- util.ForbiddenError:
- properties:
- error:
- properties:
- message:
- example: Forbidden
- type: string
- type: object
- type: object
- util.NotFoundError:
- properties:
- error:
- properties:
- message:
- example: Resource not found
- type: string
- type: object
- type: object
- util.RateLimitError:
- properties:
- error:
- properties:
- message:
- example: Rate limit exceeded
- type: string
- type: object
- type: object
- util.ServerError:
- properties:
- error:
- properties:
- message:
- example: Internal server error
- type: string
- type: object
- type: object
- util.UnauthorizedError:
- properties:
- error:
- properties:
- message:
- example: Unauthorized
+components:
+ schemas:
+ auth.DisplayCodeResponse:
+ properties:
+ challenge_id:
+ description: The challenge id associated with the displayed code and needed
+ to solve the challenge for token
+ example: 67647f5ecda913e9a2e11b26
+ type: string
+ type: object
+ auth.TokenResponse:
+ properties:
+ app_key:
+ description: The permanent app key
+ example: zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=
+ type: string
+ session_token:
+ description: The ephemeral session token
+ example: eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII
+ type: string
+ type: object
+ export.ObjectExportResponse:
+ properties:
+ path:
+ description: The path the object was exported to
+ example: /path/to/export
+ type: string
+ type: object
+ object.Block:
+ properties:
+ align:
+ description: The alignment of the block
+ enum:
+ - AlignLeft
+ - AlignCenter
+ - AlignRight
+ - AlignJustify
+ example: AlignLeft
+ type: string
+ background_color:
+ description: The background color of the block
+ example: red
+ type: string
+ children_ids:
+ description: The ids of the block's children
+ example:
+ - '[''6797ce8ecda913cde14b02dc'']'
+ items:
type: string
- type: object
- type: object
- util.ValidationError:
- properties:
- error:
- properties:
- message:
- example: Bad request
+ type: array
+ uniqueItems: false
+ file:
+ $ref: '#/components/schemas/object.File'
+ id:
+ description: The id of the block
+ example: 64394517de52ad5acb89c66c
+ type: string
+ relation:
+ $ref: '#/components/schemas/object.Relation'
+ text:
+ $ref: '#/components/schemas/object.Text'
+ vertical_align:
+ description: The vertical alignment of the block
+ enum:
+ - VerticalAlignTop
+ - VerticalAlignMiddle
+ - VerticalAlignBottom
+ example: VerticalAlignTop
+ type: string
+ type: object
+ object.CreateObjectRequest:
+ properties:
+ body:
+ description: The body of the object
+ example: This is the body of the object. Markdown syntax is supported here.
+ type: string
+ description:
+ description: The description of the object
+ example: This is a description of the object.
+ type: string
+ icon:
+ description: The icon of the object
+ example: "\U0001F4C4"
+ type: string
+ name:
+ description: The name of the object
+ example: My object
+ type: string
+ object_type_unique_key:
+ description: The unique key of the object type
+ example: ot-page
+ type: string
+ source:
+ description: The source url, only applicable for bookmarks
+ example: https://bookmark-source.com
+ type: string
+ template_id:
+ description: The id of the template to use
+ example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
+ type: string
+ type: object
+ object.Detail:
+ properties:
+ details:
+ additionalProperties: {}
+ description: The details
+ type: object
+ id:
+ description: The id of the detail
+ enum:
+ - last_modified_date
+ - last_modified_by
+ - created_date
+ - created_by
+ - last_opened_date
+ - tags
+ example: last_modified_date
+ type: string
+ type: object
+ object.File:
+ description: The file of the block, if applicable
+ properties:
+ added_at:
+ description: The added at of the file
+ type: integer
+ hash:
+ description: The hash of the file
+ type: string
+ mime:
+ description: The mime of the file
+ type: string
+ name:
+ description: The name of the file
+ type: string
+ size:
+ description: The size of the file
+ type: integer
+ state:
+ description: The state of the file
+ type: string
+ style:
+ description: The style of the file
+ type: string
+ target_object_id:
+ description: The target object id of the file
+ type: string
+ type:
+ description: The type of the file
+ type: string
+ type: object
+ object.Object:
+ description: The object
+ properties:
+ blocks:
+ description: The blocks of the object
+ items:
+ $ref: '#/components/schemas/object.Block'
+ type: array
+ uniqueItems: false
+ details:
+ description: The details of the object
+ items:
+ $ref: '#/components/schemas/object.Detail'
+ type: array
+ uniqueItems: false
+ icon:
+ description: The icon of the object
+ example: "\U0001F4C4"
+ type: string
+ id:
+ description: The id of the object
+ example: bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ
+ type: string
+ layout:
+ description: The layout of the object
+ example: basic
+ type: string
+ name:
+ description: The name of the object
+ example: My object
+ type: string
+ object:
+ description: The data model of the object
+ example: object
+ type: string
+ root_id:
+ description: The id of the object's root
+ example: bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u
+ type: string
+ snippet:
+ description: The snippet of the object, especially important for notes as
+ they don't have a name
+ example: The beginning of the object body...
+ type: string
+ space_id:
+ description: The id of the space the object is in
+ example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
+ type: string
+ type:
+ $ref: '#/components/schemas/object.Type'
+ type: object
+ object.ObjectResponse:
+ properties:
+ object:
+ $ref: '#/components/schemas/object.Object'
+ type: object
+ object.Relation:
+ description: The relation of the block, if applicable
+ properties:
+ id:
+ type: string
+ type: object
+ object.Template:
+ description: The template
+ properties:
+ icon:
+ description: The icon of the template
+ example: "\U0001F4C4"
+ type: string
+ id:
+ description: The id of the template
+ example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
+ type: string
+ name:
+ description: The name of the template
+ example: My template
+ type: string
+ object:
+ description: The data model of the object
+ example: template
+ type: string
+ type: object
+ object.TemplateResponse:
+ properties:
+ template:
+ $ref: '#/components/schemas/object.Template'
+ type: object
+ object.Text:
+ description: The text of the block, if applicable
+ properties:
+ checked:
+ description: Whether the text is checked
+ example: true
+ type: boolean
+ color:
+ description: The color of the text
+ example: red
+ type: string
+ icon:
+ description: The icon of the text
+ example: "\U0001F4C4"
+ type: string
+ style:
+ description: The style of the text
+ enum:
+ - Paragraph
+ - Header1
+ - Header2
+ - Header3
+ - Header4
+ - Quote
+ - Code
+ - Title
+ - Checkbox
+ - Marked
+ - Numbered
+ - Toggle
+ - Description
+ - Callout
+ example: Paragraph
+ type: string
+ text:
+ description: The text
+ example: Some text...
+ type: string
+ type: object
+ object.Type:
+ description: The type of the object
+ properties:
+ icon:
+ description: The icon of the type
+ example: "\U0001F4C4"
+ type: string
+ id:
+ description: The id of the type
+ example: bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu
+ type: string
+ name:
+ description: The name of the type
+ example: Page
+ type: string
+ object:
+ description: The data model of the object
+ example: type
+ type: string
+ recommended_layout:
+ description: The recommended layout of the type
+ example: todo
+ type: string
+ unique_key:
+ description: The unique key of the type
+ example: ot-page
+ type: string
+ type: object
+ object.TypeResponse:
+ properties:
+ type:
+ $ref: '#/components/schemas/object.Type'
+ type: object
+ pagination.PaginatedResponse-object_Object:
+ properties:
+ data:
+ description: The list of items in the current result set
+ items:
+ $ref: '#/components/schemas/object.Object'
+ type: array
+ uniqueItems: false
+ pagination:
+ $ref: '#/components/schemas/pagination.PaginationMeta'
+ type: object
+ pagination.PaginatedResponse-object_Template:
+ properties:
+ data:
+ description: The list of items in the current result set
+ items:
+ $ref: '#/components/schemas/object.Template'
+ type: array
+ uniqueItems: false
+ pagination:
+ $ref: '#/components/schemas/pagination.PaginationMeta'
+ type: object
+ pagination.PaginatedResponse-object_Type:
+ properties:
+ data:
+ description: The list of items in the current result set
+ items:
+ $ref: '#/components/schemas/object.Type'
+ type: array
+ uniqueItems: false
+ pagination:
+ $ref: '#/components/schemas/pagination.PaginationMeta'
+ type: object
+ pagination.PaginatedResponse-space_Member:
+ properties:
+ data:
+ description: The list of items in the current result set
+ items:
+ $ref: '#/components/schemas/space.Member'
+ type: array
+ uniqueItems: false
+ pagination:
+ $ref: '#/components/schemas/pagination.PaginationMeta'
+ type: object
+ pagination.PaginatedResponse-space_Space:
+ properties:
+ data:
+ description: The list of items in the current result set
+ items:
+ $ref: '#/components/schemas/space.Space'
+ type: array
+ uniqueItems: false
+ pagination:
+ $ref: '#/components/schemas/pagination.PaginationMeta'
+ type: object
+ pagination.PaginationMeta:
+ description: The pagination metadata for the response
+ properties:
+ has_more:
+ description: Indicates if there are more items available beyond the current
+ result set
+ example: true
+ type: boolean
+ limit:
+ description: The maximum number of items returned in the result set
+ example: 100
+ type: integer
+ offset:
+ description: The number of items skipped before starting to collect the
+ result set
+ example: 0
+ type: integer
+ total:
+ description: The total number of items available for the endpoint
+ example: 1024
+ type: integer
+ type: object
+ search.SearchRequest:
+ properties:
+ query:
+ description: The search term to look for in object names and snippets
+ example: test
+ type: string
+ sort:
+ $ref: '#/components/schemas/search.SortOptions'
+ types:
+ description: The types of objects to search for, specified by unique key
+ or ID
+ example:
+ - ot-note
+ - ot-page
+ - ot-678043f0cda9133be777049f
+ - bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q
+ items:
type: string
- type: object
- type: object
-host: localhost:31009
+ type: array
+ uniqueItems: false
+ type: object
+ search.SortOptions:
+ description: The sorting criteria and direction for the search results
+ properties:
+ direction:
+ default: desc
+ description: The direction to sort the search results
+ enum:
+ - asc
+ - desc
+ type: string
+ timestamp:
+ default: last_modified_date
+ description: The timestamp to sort the search results by
+ enum:
+ - created_date
+ - last_modified_date
+ - last_opened_date
+ type: string
+ type: object
+ space.CreateSpaceRequest:
+ properties:
+ name:
+ description: The name of the space
+ example: New Space
+ type: string
+ type: object
+ space.Member:
+ description: The member
+ properties:
+ global_name:
+ description: The global name of the member in the network
+ example: john.any
+ type: string
+ icon:
+ description: The icon of the member
+ example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100
+ type: string
+ id:
+ description: The profile object id of the member
+ example: _participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ
+ type: string
+ identity:
+ description: The identity of the member in the network
+ example: AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ
+ type: string
+ name:
+ description: The name of the member
+ example: John Doe
+ type: string
+ object:
+ description: The data model of the object
+ example: member
+ type: string
+ role:
+ description: The role of the member
+ enum:
+ - Reader
+ - Writer
+ - Owner
+ - NoPermission
+ example: Owner
+ type: string
+ type: object
+ space.MemberResponse:
+ properties:
+ member:
+ $ref: '#/components/schemas/space.Member'
+ type: object
+ space.Space:
+ description: The space
+ properties:
+ account_space_id:
+ description: The id of the account space
+ example: bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1
+ type: string
+ analytics_id:
+ description: The analytics id of the account
+ example: 624aecdd-4797-4611-9d61-a2ae5f53cf1c
+ type: string
+ archive_object_id:
+ description: The id of the archive object
+ example: bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri
+ type: string
+ device_id:
+ description: The id of the device
+ example: 12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF
+ type: string
+ gateway_url:
+ description: The gateway url to serve files and media
+ example: http://127.0.0.1:31006
+ type: string
+ home_object_id:
+ description: The id of the home object
+ example: bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya
+ type: string
+ icon:
+ description: The icon of the space
+ example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay
+ type: string
+ id:
+ description: The id of the space
+ example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
+ type: string
+ local_storage_path:
+ description: The local storage path of the account
+ example: /Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha
+ type: string
+ marketplace_workspace_id:
+ description: The id of the marketplace workspace
+ example: _anytype_marketplace
+ type: string
+ name:
+ description: The name of the space
+ example: My Space
+ type: string
+ network_id:
+ description: The network id of the space
+ example: N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU
+ type: string
+ object:
+ description: The data model of the object
+ example: space
+ type: string
+ profile_object_id:
+ description: The id of the profile object
+ example: bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4
+ type: string
+ space_view_id:
+ description: The id of the space view
+ example: bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy
+ type: string
+ tech_space_id:
+ description: The id of tech space, where objects outside of user's actual
+ spaces are stored, e.g. spaces itself
+ example: bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1
+ type: string
+ timezone:
+ description: The timezone of the account
+ example: ""
+ type: string
+ widgets_id:
+ description: The id of the widgets
+ example: bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva
+ type: string
+ workspace_object_id:
+ description: The id of the workspace object
+ example: bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y
+ type: string
+ type: object
+ space.SpaceResponse:
+ properties:
+ space:
+ $ref: '#/components/schemas/space.Space'
+ type: object
+ util.ForbiddenError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Forbidden
+ type: string
+ type: object
+ type: object
+ util.NotFoundError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Resource not found
+ type: string
+ type: object
+ type: object
+ util.RateLimitError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Rate limit exceeded
+ type: string
+ type: object
+ type: object
+ util.ServerError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Internal server error
+ type: string
+ type: object
+ type: object
+ util.UnauthorizedError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Unauthorized
+ type: string
+ type: object
+ type: object
+ util.ValidationError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Bad request
+ type: string
+ type: object
+ type: object
+ securitySchemes:
+ bearerauth:
+ bearerFormat: JWT
+ scheme: bearer
+ type: http
+externalDocs:
+ description: OpenAPI
+ url: https://swagger.io/resources/open-api/
info:
contact:
email: support@anytype.io
@@ -638,852 +634,1030 @@ info:
termsOfService: https://anytype.io/terms_of_use
title: Anytype API
version: "1.0"
+openapi: 3.1.0
paths:
/auth/display_code:
post:
- consumes:
- - application/json
parameters:
- description: App name requesting the challenge
in: query
name: app_name
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/auth.DisplayCodeResponse'
description: Challenge ID
- schema:
- $ref: '#/definitions/auth.DisplayCodeResponse'
"400":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ValidationError'
description: Invalid input
- schema:
- $ref: '#/definitions/util.ValidationError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
summary: Start new challenge
tags:
- auth
/auth/token:
post:
- consumes:
- - application/json
parameters:
- description: Challenge ID
in: query
name: challenge_id
required: true
- type: string
+ schema:
+ type: string
- description: 4-digit code retrieved from Anytype Desktop app
in: query
name: code
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/auth.TokenResponse'
description: Authentication token
- schema:
- $ref: '#/definitions/auth.TokenResponse'
"400":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ValidationError'
description: Invalid input
- schema:
- $ref: '#/definitions/util.ValidationError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
summary: Retrieve token
tags:
- auth
/search:
post:
- consumes:
- - application/json
parameters:
- - default: 0
- description: The number of items to skip before starting to collect the result
+ - description: The number of items to skip before starting to collect the result
set
in: query
name: offset
- type: integer
- - default: 100
- description: The number of items to return
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
in: query
- maximum: 1000
name: limit
- type: integer
- - description: Search parameters
- in: body
- name: request
- required: true
schema:
- $ref: '#/definitions/search.SearchRequest'
- produces:
- - application/json
+ default: 100
+ maximum: 1000
+ type: integer
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/search.SearchRequest'
+ description: Search parameters
+ required: true
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-object_Object'
description: List of objects
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-object_Object'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Search objects across all spaces
tags:
- search
/spaces:
get:
- consumes:
- - application/json
parameters:
- - default: 0
- description: The number of items to skip before starting to collect the result
+ - description: The number of items to skip before starting to collect the result
set
in: query
name: offset
- type: integer
- - default: 100
- description: The number of items to return
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
in: query
- maximum: 1000
name: limit
- type: integer
- produces:
- - application/json
+ schema:
+ default: 100
+ maximum: 1000
+ type: integer
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-space_Space'
description: List of spaces
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-space_Space'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: List spaces
tags:
- spaces
post:
- consumes:
- - application/json
- parameters:
- - description: Space to create
- in: body
- name: name
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/space.CreateSpaceRequest'
+ description: Space to create
required: true
- schema:
- $ref: '#/definitions/space.CreateSpaceRequest'
- produces:
- - application/json
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/space.SpaceResponse'
description: Space created successfully
- schema:
- $ref: '#/definitions/space.SpaceResponse'
"400":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ValidationError'
description: Bad request
- schema:
- $ref: '#/definitions/util.ValidationError'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"423":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.RateLimitError'
description: Rate limit exceeded
- schema:
- $ref: '#/definitions/util.RateLimitError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Create space
tags:
- spaces
/spaces/{space_id}:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/space.SpaceResponse'
description: Space
- schema:
- $ref: '#/definitions/space.SpaceResponse'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Space not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Get space
tags:
- spaces
/spaces/{space_id}/members:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
- - default: 0
- description: The number of items to skip before starting to collect the result
+ schema:
+ type: string
+ - description: The number of items to skip before starting to collect the result
set
in: query
name: offset
- type: integer
- - default: 100
- description: The number of items to return
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
in: query
- maximum: 1000
name: limit
- type: integer
- produces:
- - application/json
+ schema:
+ default: 100
+ maximum: 1000
+ type: integer
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-space_Member'
description: List of members
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-space_Member'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: List members
tags:
- spaces
/spaces/{space_id}/members/{member_id}:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: Member ID
in: path
name: member_id
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/space.MemberResponse'
description: Member
- schema:
- $ref: '#/definitions/space.MemberResponse'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Member not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Get member
tags:
- spaces
/spaces/{space_id}/objects:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
- - default: 0
- description: The number of items to skip before starting to collect the result
+ schema:
+ type: string
+ - description: The number of items to skip before starting to collect the result
set
in: query
name: offset
- type: integer
- - default: 100
- description: The number of items to return
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
in: query
- maximum: 1000
name: limit
- type: integer
- produces:
- - application/json
+ schema:
+ default: 100
+ maximum: 1000
+ type: integer
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-object_Object'
description: List of objects
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-object_Object'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: List objects
tags:
- objects
post:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
- - description: Object to create
- in: body
- name: object
- required: true
schema:
- $ref: '#/definitions/object.CreateObjectRequest'
- produces:
- - application/json
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/object.CreateObjectRequest'
+ description: Object to create
+ required: true
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/object.ObjectResponse'
description: The created object
- schema:
- $ref: '#/definitions/object.ObjectResponse'
"400":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ValidationError'
description: Bad request
- schema:
- $ref: '#/definitions/util.ValidationError'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"423":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.RateLimitError'
description: Rate limit exceeded
- schema:
- $ref: '#/definitions/util.RateLimitError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Create object
tags:
- objects
/spaces/{space_id}/objects/{object_id}:
delete:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: Object ID
in: path
name: object_id
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/object.ObjectResponse'
description: The deleted object
- schema:
- $ref: '#/definitions/object.ObjectResponse'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"403":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ForbiddenError'
description: Forbidden
- schema:
- $ref: '#/definitions/util.ForbiddenError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Resource not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"423":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.RateLimitError'
description: Rate limit exceeded
- schema:
- $ref: '#/definitions/util.RateLimitError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Delete object
tags:
- objects
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: Object ID
in: path
name: object_id
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/object.ObjectResponse'
description: The requested object
- schema:
- $ref: '#/definitions/object.ObjectResponse'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Resource not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Get object
tags:
- objects
/spaces/{space_id}/objects/{object_id}/export/{format}:
post:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: Object ID
in: path
name: object_id
required: true
- type: string
+ schema:
+ type: string
- description: Export format
- enum:
- - markdown
- - protobuf
in: path
name: format
required: true
- type: string
- produces:
- - application/json
+ schema:
+ enum:
+ - markdown
+ - protobuf
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/export.ObjectExportResponse'
description: Object exported successfully
- schema:
- $ref: '#/definitions/export.ObjectExportResponse'
"400":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ValidationError'
description: Bad request
- schema:
- $ref: '#/definitions/util.ValidationError'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Export object
tags:
- export
/spaces/{space_id}/search:
post:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
- - default: 0
- description: The number of items to skip before starting to collect the result
+ schema:
+ type: string
+ - description: The number of items to skip before starting to collect the result
set
in: query
name: offset
- type: integer
- - default: 100
- description: The number of items to return
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
in: query
- maximum: 1000
name: limit
- type: integer
- - description: Search parameters
- in: body
- name: request
- required: true
schema:
- $ref: '#/definitions/search.SearchRequest'
- produces:
- - application/json
+ default: 100
+ maximum: 1000
+ type: integer
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/search.SearchRequest'
+ description: Search parameters
+ required: true
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-object_Object'
description: List of objects
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-object_Object'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Search objects within a space
tags:
- search
/spaces/{space_id}/types:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
- - default: 0
- description: The number of items to skip before starting to collect the result
+ schema:
+ type: string
+ - description: The number of items to skip before starting to collect the result
set
in: query
name: offset
- type: integer
- - default: 100
- description: The number of items to return
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
in: query
- maximum: 1000
name: limit
- type: integer
- produces:
- - application/json
+ schema:
+ default: 100
+ maximum: 1000
+ type: integer
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-object_Type'
description: List of types
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-object_Type'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: List types
tags:
- types
/spaces/{space_id}/types/{type_id}:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: Type ID
in: path
name: type_id
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/object.TypeResponse'
description: The requested type
- schema:
- $ref: '#/definitions/object.TypeResponse'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Resource not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Get type
tags:
- types
/spaces/{space_id}/types/{type_id}/templates:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: Type ID
in: path
name: type_id
required: true
- type: string
- - default: 0
- description: The number of items to skip before starting to collect the result
+ schema:
+ type: string
+ - description: The number of items to skip before starting to collect the result
set
in: query
name: offset
- type: integer
- - default: 100
- description: The number of items to return
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
in: query
- maximum: 1000
name: limit
- type: integer
- produces:
- - application/json
+ schema:
+ default: 100
+ maximum: 1000
+ type: integer
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-object_Template'
description: List of templates
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-object_Template'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: List templates
tags:
- types
/spaces/{space_id}/types/{type_id}/templates/{template_id}:
get:
- consumes:
- - application/json
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: Type ID
in: path
name: type_id
required: true
- type: string
+ schema:
+ type: string
- description: Template ID
in: path
name: template_id
required: true
- type: string
- produces:
- - application/json
+ schema:
+ type: string
responses:
"200":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/object.TemplateResponse'
description: The requested template
- schema:
- $ref: '#/definitions/object.TemplateResponse'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Resource not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
+ security:
+ - bearerauth: []
summary: Get template
tags:
- types
/v1/spaces/{space_id}/lists/{list_id}/objects:
- delete:
- consumes:
- - application/json
+ get:
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: List ID
in: path
name: list_id
required: true
- type: string
- - description: List of object IDs
- in: body
- name: objects
- required: true
schema:
- items:
- type: string
- type: array
- produces:
- - application/json
+ type: string
+ - description: The number of items to skip before starting to collect the result
+ set
+ in: query
+ name: offset
+ schema:
+ default: 0
+ type: integer
+ - description: The number of items to return
+ in: query
+ name: limit
+ schema:
+ type: integer
responses:
"200":
- description: Objects removed successfully
- schema:
- type: string
- "400":
- description: Bad request
- schema:
- $ref: '#/definitions/util.ValidationError'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/pagination.PaginatedResponse-object_Object'
+ description: List of objects
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
- summary: Remove objects from list
+ security:
+ - bearerauth: []
+ summary: Get objects in list
tags:
- lists
- get:
- consumes:
- - application/json
+ post:
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: List ID
in: path
name: list_id
required: true
- type: string
- - default: 0
- description: The number of items to skip before starting to collect the result
- set
- in: query
- name: offset
- type: integer
- - description: The number of items to return
- in: query
- name: limit
- type: integer
- produces:
- - application/json
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ items:
+ type: string
+ type: array
+ description: List of object IDs
+ required: true
responses:
"200":
- description: List of objects
- schema:
- $ref: '#/definitions/pagination.PaginatedResponse-object_Object'
+ content:
+ application/json:
+ schema:
+ type: string
+ description: Objects added successfully
+ "400":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ValidationError'
+ description: Bad request
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
- summary: Get objects in list
+ security:
+ - bearerauth: []
+ summary: Add objects to list
tags:
- lists
- post:
- consumes:
- - application/json
+ /v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}:
+ delete:
parameters:
- description: Space ID
in: path
name: space_id
required: true
- type: string
+ schema:
+ type: string
- description: List ID
in: path
name: list_id
required: true
- type: string
- - description: List of object IDs
- in: body
- name: objects
+ schema:
+ type: string
+ - description: Object ID
+ in: path
+ name: object_id
required: true
schema:
- items:
- type: string
- type: array
- produces:
- - application/json
+ type: string
responses:
"200":
- description: Objects added successfully
- schema:
- type: string
+ content:
+ application/json:
+ schema:
+ type: string
+ description: Objects removed successfully
"400":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ValidationError'
description: Bad request
- schema:
- $ref: '#/definitions/util.ValidationError'
"401":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.UnauthorizedError'
description: Unauthorized
- schema:
- $ref: '#/definitions/util.UnauthorizedError'
"404":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.NotFoundError'
description: Not found
- schema:
- $ref: '#/definitions/util.NotFoundError'
"500":
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/util.ServerError'
description: Internal server error
- schema:
- $ref: '#/definitions/util.ServerError'
- summary: Add objects to list
+ security:
+ - bearerauth: []
+ summary: Remove object from list
tags:
- lists
-securityDefinitions:
- ApiKeyAuth:
- in: header
- name: Authorization
- type: apiKey
-swagger: "2.0"
+servers:
+- url: localhost:31009/v1
diff --git a/core/api/internal/export/handler.go b/core/api/internal/export/handler.go
index c2ae3a2f86..b0a2813a42 100644
--- a/core/api/internal/export/handler.go
+++ b/core/api/internal/export/handler.go
@@ -21,6 +21,7 @@ import (
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/objects/{object_id}/export/{format} [post]
func GetObjectExportHandler(s *ExportService) gin.HandlerFunc {
return func(c *gin.Context) {
diff --git a/core/api/internal/list/handler.go b/core/api/internal/list/handler.go
index 0830390f53..c5c6871ae5 100644
--- a/core/api/internal/list/handler.go
+++ b/core/api/internal/list/handler.go
@@ -13,7 +13,6 @@ import (
//
// @Summary Get objects in list
// @Tags lists
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param list_id path string true "List ID"
@@ -23,6 +22,7 @@ import (
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Not found"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [get]
func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -60,6 +60,7 @@ func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Not found"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [post]
func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -88,34 +89,28 @@ func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
}
}
-// RemoveObjectsFromListHandler
+// RemoveObjectFromListHandler
//
-// @Summary Remove objects from list
+// @Summary Remove object from list
// @Tags lists
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param list_id path string true "List ID"
-// @Param objects body []string true "List of object IDs"
+// @Param object_id path string true "Object ID"
// @Success 200 {object} string "Objects removed successfully"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Not found"
// @Failure 500 {object} util.ServerError "Internal server error"
-// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [delete]
-func RemoveObjectsFromListHandler(s *ListService) gin.HandlerFunc {
+// @Security bearerauth
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects/{object_id} [delete]
+func RemoveObjectFromListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
listId := c.Param("list_id")
+ objectId := c.Param("object_id")
- objects := []string{}
- if err := c.ShouldBindJSON(&objects); err != nil {
- apiErr := util.CodeToAPIError(http.StatusBadRequest, err.Error())
- c.JSON(http.StatusBadRequest, apiErr)
- return
- }
-
- err := s.RemoveObjectsFromList(c, spaceId, listId, objects)
+ err := s.RemoveObjectFromList(c, spaceId, listId, objectId)
code := util.MapErrorCode(err,
util.ErrToCode(ErrFailedRemoveObjectsFromList, http.StatusInternalServerError),
)
diff --git a/core/api/internal/list/service.go b/core/api/internal/list/service.go
index 625e560506..75e6f8407c 100644
--- a/core/api/internal/list/service.go
+++ b/core/api/internal/list/service.go
@@ -20,7 +20,7 @@ var (
type Service interface {
GetObjectsInList(ctx context.Context, spaceId string, listId string, offset, limit int) ([]object.Object, int, bool, error)
AddObjectsToList(ctx context.Context, spaceId string, listId string, objectIds []string) error
- RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIds []string) error
+ RemoveObjectFromList(ctx context.Context, spaceId string, listId string, objectIds []string) error
}
type ListService struct {
@@ -76,11 +76,11 @@ func (s *ListService) AddObjectsToList(ctx context.Context, spaceId string, list
return nil
}
-// RemoveObjectsFromList removes objects from a list
-func (s *ListService) RemoveObjectsFromList(ctx context.Context, spaceId string, listId string, objectIds []string) error {
+// RemoveObjectFromList removes objects from a list
+func (s *ListService) RemoveObjectFromList(ctx context.Context, spaceId string, listId string, objectId string) error {
resp := s.mw.ObjectCollectionRemove(ctx, &pb.RpcObjectCollectionRemoveRequest{
ContextId: spaceId,
- ObjectIds: objectIds,
+ ObjectIds: []string{objectId},
})
if resp.Error.Code != pb.RpcObjectCollectionRemoveResponseError_NULL {
diff --git a/core/api/internal/object/handler.go b/core/api/internal/object/handler.go
index 57c1e2e877..a8a0aa25d1 100644
--- a/core/api/internal/object/handler.go
+++ b/core/api/internal/object/handler.go
@@ -13,7 +13,6 @@ import (
//
// @Summary List objects
// @Tags objects
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
@@ -21,6 +20,7 @@ import (
// @Success 200 {object} pagination.PaginatedResponse[Object] "List of objects"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/objects [get]
func GetObjectsHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -49,7 +49,6 @@ func GetObjectsHandler(s *ObjectService) gin.HandlerFunc {
//
// @Summary Get object
// @Tags objects
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param object_id path string true "Object ID"
@@ -57,6 +56,7 @@ func GetObjectsHandler(s *ObjectService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Resource not found"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/objects/{object_id} [get]
func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -83,7 +83,6 @@ func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
//
// @Summary Delete object
// @Tags objects
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param object_id path string true "Object ID"
@@ -93,6 +92,7 @@ func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Failure 404 {object} util.NotFoundError "Resource not found"
// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/objects/{object_id} [delete]
func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -129,6 +129,7 @@ func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/objects [post]
func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -165,7 +166,6 @@ func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
//
// @Summary List types
// @Tags types
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
@@ -173,6 +173,7 @@ func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Success 200 {object} pagination.PaginatedResponse[Type] "List of types"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/types [get]
func GetTypesHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -199,7 +200,6 @@ func GetTypesHandler(s *ObjectService) gin.HandlerFunc {
//
// @Summary Get type
// @Tags types
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param type_id path string true "Type ID"
@@ -207,6 +207,7 @@ func GetTypesHandler(s *ObjectService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Resource not found"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/types/{type_id} [get]
func GetTypeHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -233,7 +234,6 @@ func GetTypeHandler(s *ObjectService) gin.HandlerFunc {
//
// @Summary List templates
// @Tags types
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param type_id path string true "Type ID"
@@ -242,6 +242,7 @@ func GetTypeHandler(s *ObjectService) gin.HandlerFunc {
// @Success 200 {object} pagination.PaginatedResponse[Template] "List of templates"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/types/{type_id}/templates [get]
func GetTemplatesHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -272,7 +273,6 @@ func GetTemplatesHandler(s *ObjectService) gin.HandlerFunc {
//
// @Summary Get template
// @Tags types
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param type_id path string true "Type ID"
@@ -281,6 +281,7 @@ func GetTemplatesHandler(s *ObjectService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Resource not found"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/types/{type_id}/templates/{template_id} [get]
func GetTemplateHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
diff --git a/core/api/internal/search/handler.go b/core/api/internal/search/handler.go
index e3ffe62ed8..57bbe33182 100644
--- a/core/api/internal/search/handler.go
+++ b/core/api/internal/search/handler.go
@@ -21,6 +21,7 @@ import (
// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /search [post]
func GlobalSearchHandler(s *SearchService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -62,6 +63,7 @@ func GlobalSearchHandler(s *SearchService) gin.HandlerFunc {
// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/search [post]
func SearchHandler(s *SearchService) gin.HandlerFunc {
return func(c *gin.Context) {
diff --git a/core/api/internal/space/handler.go b/core/api/internal/space/handler.go
index 5dbbd2cd83..8c67c671b5 100644
--- a/core/api/internal/space/handler.go
+++ b/core/api/internal/space/handler.go
@@ -13,13 +13,13 @@ import (
//
// @Summary List spaces
// @Tags spaces
-// @Accept json
// @Produce json
// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
// @Param limit query int false "The number of items to return" default(100) maximum(1000)
// @Success 200 {object} pagination.PaginatedResponse[Space] "List of spaces"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces [get]
func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -46,13 +46,13 @@ func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
//
// @Summary Get space
// @Tags spaces
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Success 200 {object} SpaceResponse "Space"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Space not found"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id} [get]
func GetSpaceHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -86,6 +86,7 @@ func GetSpaceHandler(s *SpaceService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces [post]
func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -115,7 +116,6 @@ func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
//
// @Summary List members
// @Tags spaces
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
@@ -123,6 +123,7 @@ func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
// @Success 200 {object} pagination.PaginatedResponse[Member] "List of members"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/members [get]
func GetMembersHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
@@ -149,7 +150,6 @@ func GetMembersHandler(s *SpaceService) gin.HandlerFunc {
//
// @Summary Get member
// @Tags spaces
-// @Accept json
// @Produce json
// @Param space_id path string true "Space ID"
// @Param member_id path string true "Member ID"
@@ -157,6 +157,7 @@ func GetMembersHandler(s *SpaceService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Member not found"
// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
// @Router /spaces/{space_id}/members/{member_id} [get]
func GetMemberHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
diff --git a/core/api/server/router.go b/core/api/server/router.go
index 6bc0174119..f3397da1c0 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -70,7 +70,7 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
// List
v1.GET("/spaces/:space_id/lists/:list_id/objects", list.GetObjectsInListHandler(s.listService))
v1.POST("/spaces/:space_id/lists/:list_id/objects", list.AddObjectsToListHandler(s.listService))
- v1.DELETE("/spaces/:space_id/lists/:list_id/objects", list.RemoveObjectsFromListHandler(s.listService))
+ v1.DELETE("/spaces/:space_id/lists/:list_id/objects/:object_id", s.rateLimit(maxWriteRequestsPerSecond), list.RemoveObjectFromListHandler(s.listService))
// Object
v1.GET("/spaces/:space_id/objects", object.GetObjectsHandler(s.objectService))
diff --git a/core/api/service.go b/core/api/service.go
index d6cb17d475..4917f51d82 100644
--- a/core/api/service.go
+++ b/core/api/service.go
@@ -49,22 +49,20 @@ func (s *apiService) Name() (name string) {
// Init initializes the API service.
//
-// @title Anytype API
-// @version 1.0
-// @description This API allows interaction with Anytype resources such as spaces, objects and types.
-// @termsOfService https://anytype.io/terms_of_use
-// @contact.name Anytype Support
-// @contact.url https://anytype.io/contact
-// @contact.email support@anytype.io
-// @license.name Any Source Available License 1.0
-// @license.url https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md
-// @host localhost:31009
-// @BasePath /v1
-// @securityDefinitions.apikey ApiKeyAuth
-// @in header
-// @name Authorization
-// @externalDocs.description OpenAPI
-// @externalDocs.url https://swagger.io/resources/open-api/
+// @title Anytype API
+// @version 1.0
+// @description This API allows interaction with Anytype resources such as spaces, objects and types.
+// @termsOfService https://anytype.io/terms_of_use
+// @contact.name Anytype Support
+// @contact.url https://anytype.io/contact
+// @contact.email support@anytype.io
+// @license.name Any Source Available License 1.0
+// @license.url https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md
+// @host localhost:31009
+// @BasePath /v1
+// @securitydefinitions.bearerauth BearerAuth
+// @externalDocs.description OpenAPI
+// @externalDocs.url https://swagger.io/resources/open-api/
func (s *apiService) Init(a *app.App) (err error) {
s.listenAddr = a.MustComponent(config.CName).(*config.Config).JsonApiListenAddr
s.accountService = a.MustComponent(account.CName).(account.Service)
diff --git a/go.mod b/go.mod
index 829142b213..bfba1e94a5 100644
--- a/go.mod
+++ b/go.mod
@@ -169,10 +169,10 @@ require (
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
- github.com/go-openapi/jsonpointer v0.19.5 // indirect
- github.com/go-openapi/jsonreference v0.19.6 // indirect
- github.com/go-openapi/spec v0.20.4 // indirect
- github.com/go-openapi/swag v0.19.15 // indirect
+ github.com/go-openapi/jsonpointer v0.19.6 // indirect
+ github.com/go-openapi/jsonreference v0.20.2 // indirect
+ github.com/go-openapi/spec v0.20.9 // indirect
+ github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-pkgz/expirable-cache/v3 v3.0.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
@@ -220,7 +220,7 @@ require (
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-libp2p v0.38.2 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
- github.com/mailru/easyjson v0.7.6 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/miekg/dns v1.1.62 // indirect
@@ -265,6 +265,8 @@ require (
github.com/spf13/viper v1.15.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
+ github.com/sv-tools/openapi v0.2.1 // indirect
+ github.com/swaggo/swag/v2 v2.0.0-rc4 // indirect
github.com/tetratelabs/wazero v1.8.1 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
diff --git a/go.sum b/go.sum
index 99d0be11d0..dbfd5264e2 100644
--- a/go.sum
+++ b/go.sum
@@ -353,13 +353,22 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
+github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
+github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
+github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
+github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
+github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
+github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-pkgz/expirable-cache/v3 v3.0.0 h1:u3/gcu3sabLYiTCevoRKv+WzjIn5oo7P8XtiXBeRDLw=
github.com/go-pkgz/expirable-cache/v3 v3.0.0/go.mod h1:2OQiDyEGQalYecLWmXprm3maPXeVb5/6/X7yRPYTzec=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
@@ -684,6 +693,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -728,6 +738,8 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matishsiao/goInfo v0.0.0-20240924010139-10388a85396f h1:XDrsC/9hdgiU9ecceSmYsS2E3fBtFiYc34dAMFgegnM=
github.com/matishsiao/goInfo v0.0.0-20240924010139-10388a85396f/go.mod h1:aEt7p9Rvh67BYApmZwNDPpgircTO2kgdmDUoF/1QmwA=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -1056,12 +1068,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
+github.com/sv-tools/openapi v0.2.1 h1:ES1tMQMJFGibWndMagvdoo34T1Vllxr1Nlm5wz6b1aA=
+github.com/sv-tools/openapi v0.2.1/go.mod h1:k5VuZamTw1HuiS9p2Wl5YIDWzYnHG6/FgPOSFXLAhGg=
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
+github.com/swaggo/swag/v2 v2.0.0-rc4 h1:SZ8cK68gcV6cslwrJMIOqPkJELRwq4gmjvk77MrvHvY=
+github.com/swaggo/swag/v2 v2.0.0-rc4/go.mod h1:Ow7Y8gF16BTCDn8YxZbyKn8FkMLRUHekv1kROJZpbvE=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550=
github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
From 1c87b864a51baa828c0f993320d30f334efec40b Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 16 Feb 2025 13:56:17 +0100
Subject: [PATCH 22/31] GO-4459: Add http prefix to host
---
core/api/docs/docs.go | 2 +-
core/api/docs/swagger.json | 2 +-
core/api/docs/swagger.yaml | 2 +-
core/api/service.go | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 2faeb5526a..01dd8e76e0 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -12,7 +12,7 @@ const docTemplate = `{
"paths": {"/auth/display_code":{"post":{"parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
"openapi": "3.1.0",
"servers": [
- {"url":"localhost:31009/v1"}
+ {"url":"http://localhost:31009/v1"}
]
}`
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index c79693d6bf..3247b1acfb 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -5,6 +5,6 @@
"paths": {"/auth/display_code":{"post":{"parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
"openapi": "3.1.0",
"servers": [
- {"url":"localhost:31009/v1"}
+ {"url":"http://localhost:31009/v1"}
]
}
\ No newline at end of file
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index deb31aec21..2c3ff7a8e8 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -1660,4 +1660,4 @@ paths:
tags:
- lists
servers:
-- url: localhost:31009/v1
+- url: http://localhost:31009/v1
diff --git a/core/api/service.go b/core/api/service.go
index 4917f51d82..4d98e334d7 100644
--- a/core/api/service.go
+++ b/core/api/service.go
@@ -58,7 +58,7 @@ func (s *apiService) Name() (name string) {
// @contact.email support@anytype.io
// @license.name Any Source Available License 1.0
// @license.url https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md
-// @host localhost:31009
+// @host http://localhost:31009
// @BasePath /v1
// @securitydefinitions.bearerauth BearerAuth
// @externalDocs.description OpenAPI
From 5b5da7d7071f152e2844cf03b82b11304aceb0a6 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 16 Feb 2025 18:21:41 +0100
Subject: [PATCH 23/31] GO-4459: Add `swagger` Make target to generate and
format swagger docs
---
Makefile | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Makefile b/Makefile
index cffe394874..2927a6e109 100644
--- a/Makefile
+++ b/Makefile
@@ -338,6 +338,12 @@ else
@golangci-lint run -v ./... --new-from-rev=origin/main --timeout 15m --fix
endif
+swagger:
+ @echo 'Generating swagger docs...'
+ @swag init --v3.1 -q -d core/api -g service.go -o core/api/docs
+ @echo 'Formatting swagger docs...'
+ @swag fmt -d core/api
+
### Tantivy Section
REPO := anyproto/tantivy-go
From fd66a264f83c5c56194897b542fd927d57d752aa Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Sun, 16 Feb 2025 19:14:18 +0100
Subject: [PATCH 24/31] GO-4459: Add resolveTag method to handle tag/status
option as string instead of list bug
---
core/api/internal/object/service.go | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 0079b90952..ad86898c79 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -560,6 +560,12 @@ func (s *ObjectService) convertValue(value *types.Value, format string, key stri
}
return member
}
+
+ // TODO: investigate how this is possible? select option not list and not returned in further details
+ if format == "select" || format == "multi_select" {
+ return s.resolveTag(details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), kind.StringValue)
+ }
+
return kind.StringValue
case *types.Value_BoolValue:
return kind.BoolValue
@@ -604,6 +610,28 @@ func (s *ObjectService) getRelationFormatMap(relationLinks []*model.RelationLink
return relationFormatMap
}
+// TODO: remove once bug of select option not being returned in details is fixed
+func (s *ObjectService) resolveTag(spaceId, tagId string) Tag {
+ if tagId == "" {
+ return Tag{}
+ }
+
+ resp := s.mw.ObjectShow(context.Background(), &pb.RpcObjectShowRequest{
+ SpaceId: spaceId,
+ ObjectId: tagId,
+ })
+
+ if resp.Error.Code != pb.RpcObjectShowResponseError_NULL {
+ return Tag{}
+ }
+
+ return Tag{
+ Id: tagId,
+ Name: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyName.String()].GetStringValue(),
+ Color: resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeyRelationOptionColor.String()].GetStringValue(),
+ }
+}
+
// getTags returns the list of tags from the ObjectShowResponse
func (s *ObjectService) getTags(key string, details []*model.ObjectViewDetailsSet) []Tag {
tags := []Tag{}
From cdf1787bf1e341bb8941db4f6e54e4c8554e266c Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Mon, 17 Feb 2025 13:54:41 +0100
Subject: [PATCH 25/31] GO-4459: Add layout align to excluded relations
---
core/api/internal/object/service.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index ad86898c79..420e2824df 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -497,6 +497,7 @@ func (s *ObjectService) getDetails(resp *pb.RpcObjectShowResponse) []Detail {
bundle.RelationKeyLinks.String(): true,
bundle.RelationKeyBacklinks.String(): true,
bundle.RelationKeySourceObject.String(): true,
+ bundle.RelationKeyLayoutAlign.String(): true,
}
var details []Detail
From ff88402e626dee7aed230b9673794d0e04b29fe8 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Mon, 17 Feb 2025 15:50:38 +0100
Subject: [PATCH 26/31] GO-4459: Add missing filter condition for relation name
resolution
---
core/api/internal/object/service.go | 6 +++---
core/api/util/util.go | 17 ++++++++++-------
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 420e2824df..3565976a7e 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -526,11 +526,11 @@ func (s *ObjectService) getDetails(resp *pb.RpcObjectShowResponse) []Detail {
func (s *ObjectService) getRelation(key string, resp *pb.RpcObjectShowResponse) (id string, name string) {
relation, err := bundle.GetRelation(domain.RelationKey(key))
if err != nil {
- relation, err = util.ResolveRelationKeyToRelationName(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), key)
+ name, err = util.ResolveRelationKeyToRelationName(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), key)
if err != nil {
- return strcase.ToSnake(key), key
+ return key, key
}
- return key, relation.Name
+ return key, name
}
// special cases of relation keys and names
diff --git a/core/api/util/util.go b/core/api/util/util.go
index 25eacf1d25..568a5c3bc5 100644
--- a/core/api/util/util.go
+++ b/core/api/util/util.go
@@ -61,7 +61,7 @@ func ResolveUniqueKeyToTypeId(mw service.ClientCommandsServer, spaceId string, u
return resp.Records[0].Fields[bundle.RelationKeyId.String()].GetStringValue(), nil
}
-func ResolveRelationKeyToRelationName(mw service.ClientCommandsServer, spaceId string, relationKey string) (relation *model.Relation, err error) {
+func ResolveRelationKeyToRelationName(mw service.ClientCommandsServer, spaceId string, relationKey string) (relation string, err error) {
resp := mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
SpaceId: spaceId,
Filters: []*model.BlockContentDataviewFilter{
@@ -70,19 +70,22 @@ func ResolveRelationKeyToRelationName(mw service.ClientCommandsServer, spaceId s
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(relationKey),
},
+ {
+ RelationKey: bundle.RelationKeyLayout.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.Int64(int64(model.ObjectType_relation)),
+ },
},
- Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeyName.String()},
+ Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeyName.String(), bundle.RelationKeyLayout.String()},
})
if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
- return &model.Relation{}, ErrFailedSearchType
+ return "", ErrFailedSearchType
}
if len(resp.Records) == 0 {
- return &model.Relation{}, ErrorTypeNotFound
+ return "", ErrorTypeNotFound
}
- return &model.Relation{
- Name: resp.Records[0].Fields[bundle.RelationKeyName.String()].GetStringValue(),
- }, nil
+ return resp.Records[0].Fields[bundle.RelationKeyName.String()].GetStringValue(), nil
}
From 394922dae773ae221137d7283a2c0dd288372d7e Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Mon, 17 Feb 2025 17:05:45 +0100
Subject: [PATCH 27/31] GO-4459: Fix tests for space and object
---
core/api/internal/object/service_test.go | 107 +++++++++++++++++++++--
core/api/internal/search/service_test.go | 100 +++++++++++++++++++++
2 files changed, 201 insertions(+), 6 deletions(-)
diff --git a/core/api/internal/object/service_test.go b/core/api/internal/object/service_test.go
index 447f2f6913..1c78386322 100644
--- a/core/api/internal/object/service_test.go
+++ b/core/api/internal/object/service_test.go
@@ -65,6 +65,29 @@ func TestObjectService_ListObjects(t *testing.T) {
ctx := context.Background()
fx := newFixture(t)
+ // Mock template type resolution
+ fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
+ SpaceId: mockedSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyUniqueKey.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String("ot-template"),
+ },
+ },
+ Keys: []string{bundle.RelationKeyId.String()},
+ }).Return(&pb.RpcObjectSearchResponse{
+ Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Records: []*types.Struct{
+ {
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
+ },
+ },
+ },
+ }).Once()
+
+ // Mock object search
fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
SpaceId: mockedSpaceId,
Filters: []*model.BlockContentDataviewFilter{
@@ -82,6 +105,18 @@ func TestObjectService_ListObjects(t *testing.T) {
int(model.ObjectType_participant),
}...),
},
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyType.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.String(mockedTypeId),
+ },
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyIsHidden.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.Bool(true),
+ },
},
Sorts: []*model.BlockContentDataviewSort{{
RelationKey: bundle.RelationKeyLastModifiedDate.String(),
@@ -257,14 +292,74 @@ func TestObjectService_ListObjects(t *testing.T) {
ctx := context.Background()
fx := newFixture(t)
- fx.mwMock.On("ObjectSearch", mock.Anything, mock.Anything).
- Return(&pb.RpcObjectSearchResponse{
- Records: []*types.Struct{},
- Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
- }).Once()
+ // Mock template type resolution
+ fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
+ SpaceId: mockedSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyUniqueKey.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String("ot-template"),
+ },
+ },
+ Keys: []string{bundle.RelationKeyId.String()},
+ }).Return(&pb.RpcObjectSearchResponse{
+ Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Records: []*types.Struct{
+ {
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedTypeId),
+ },
+ },
+ },
+ }).Once()
+
+ // Mock object search
+ fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
+ SpaceId: mockedSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyLayout.String(),
+ Condition: model.BlockContentDataviewFilter_In,
+ Value: pbtypes.IntList([]int{
+ int(model.ObjectType_basic),
+ int(model.ObjectType_profile),
+ int(model.ObjectType_todo),
+ int(model.ObjectType_note),
+ int(model.ObjectType_bookmark),
+ int(model.ObjectType_set),
+ int(model.ObjectType_collection),
+ int(model.ObjectType_participant),
+ }...),
+ },
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyType.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.String(mockedTypeId),
+ },
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyIsHidden.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.Bool(true),
+ },
+ },
+ Sorts: []*model.BlockContentDataviewSort{{
+ RelationKey: bundle.RelationKeyLastModifiedDate.String(),
+ Type: model.BlockContentDataviewSort_Desc,
+ Format: model.RelationFormat_longtext,
+ IncludeTime: true,
+ EmptyPlacement: model.BlockContentDataviewSort_NotSpecified,
+ }},
+ Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeyName.String()},
+ }).Return(&pb.RpcObjectSearchResponse{
+ Records: []*types.Struct{},
+ Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ }).Once()
// when
- objects, total, hasMore, err := fx.ListObjects(ctx, "empty-space", offset, limit)
+ objects, total, hasMore, err := fx.ListObjects(ctx, mockedSpaceId, offset, limit)
// then
require.NoError(t, err)
diff --git a/core/api/internal/search/service_test.go b/core/api/internal/search/service_test.go
index c6d1e023ad..f7e3eb288a 100644
--- a/core/api/internal/search/service_test.go
+++ b/core/api/internal/search/service_test.go
@@ -120,6 +120,28 @@ func TestSearchService_GlobalSearch(t *testing.T) {
Error: &pb.RpcWorkspaceOpenResponseError{Code: pb.RpcWorkspaceOpenResponseError_NULL},
}).Once()
+ // Mock template type resolution
+ fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
+ SpaceId: mockedSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyUniqueKey.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String("ot-template"),
+ },
+ },
+ Keys: []string{bundle.RelationKeyId.String()},
+ }).Return(&pb.RpcObjectSearchResponse{
+ Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Records: []*types.Struct{
+ {
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedType),
+ },
+ },
+ },
+ }).Once()
+
// Mock objects in space
fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
SpaceId: mockedSpaceId,
@@ -148,6 +170,12 @@ func TestSearchService_GlobalSearch(t *testing.T) {
Condition: model.BlockContentDataviewFilter_NotEqual,
Value: pbtypes.Bool(true),
},
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyType.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.String(mockedType),
+ },
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
@@ -406,6 +434,28 @@ func TestSearchService_Search(t *testing.T) {
ctx := context.Background()
fx := newFixture(t)
+ // Mock template type resolution
+ fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
+ SpaceId: mockedSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyUniqueKey.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String("ot-template"),
+ },
+ },
+ Keys: []string{bundle.RelationKeyId.String()},
+ }).Return(&pb.RpcObjectSearchResponse{
+ Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Records: []*types.Struct{
+ {
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedType),
+ },
+ },
+ },
+ }).Once()
+
// Mock objects in space
fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
SpaceId: mockedSpaceId,
@@ -434,6 +484,12 @@ func TestSearchService_Search(t *testing.T) {
Condition: model.BlockContentDataviewFilter_NotEqual,
Value: pbtypes.Bool(true),
},
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyType.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.String(mockedType),
+ },
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
@@ -530,6 +586,28 @@ func TestSearchService_Search(t *testing.T) {
ctx := context.Background()
fx := newFixture(t)
+ // Mock template type resolution
+ fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
+ SpaceId: mockedSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyUniqueKey.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String("ot-template"),
+ },
+ },
+ Keys: []string{bundle.RelationKeyId.String()},
+ }).Return(&pb.RpcObjectSearchResponse{
+ Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Records: []*types.Struct{
+ {
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedType),
+ },
+ },
+ },
+ }).Once()
+
fx.mwMock.On("ObjectSearch", mock.Anything, mock.Anything).Return(&pb.RpcObjectSearchResponse{
Records: []*types.Struct{},
Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
@@ -550,6 +628,28 @@ func TestSearchService_Search(t *testing.T) {
ctx := context.Background()
fx := newFixture(t)
+ // Mock template type resolution
+ fx.mwMock.On("ObjectSearch", mock.Anything, &pb.RpcObjectSearchRequest{
+ SpaceId: mockedSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ RelationKey: bundle.RelationKeyUniqueKey.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String("ot-template"),
+ },
+ },
+ Keys: []string{bundle.RelationKeyId.String()},
+ }).Return(&pb.RpcObjectSearchResponse{
+ Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
+ Records: []*types.Struct{
+ {
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyId.String(): pbtypes.String(mockedType),
+ },
+ },
+ },
+ }).Once()
+
fx.mwMock.On("ObjectSearch", mock.Anything, mock.Anything).Return(&pb.RpcObjectSearchResponse{
Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_UNKNOWN_ERROR},
}).Once()
From 79e72a51fe1bfb9c98b2a86a888a6f8cbd66bc87 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Mon, 17 Feb 2025 17:06:50 +0100
Subject: [PATCH 28/31] GO-4459: Remove templates from search and object list
results
---
core/api/internal/object/service.go | 19 +++++++++++++++++++
core/api/internal/search/service.go | 27 +++++++++++++++++++++++----
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 3565976a7e..acc74b2a5b 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -64,10 +64,13 @@ func NewService(mw service.ClientCommandsServer, spaceService *space.SpaceServic
// ListObjects retrieves a paginated list of objects in a specific space.
func (s *ObjectService) ListObjects(ctx context.Context, spaceId string, offset int, limit int) (objects []Object, total int, hasMore bool, err error) {
+ typeId, err := util.ResolveUniqueKeyToTypeId(s.mw, spaceId, "ot-template")
+
resp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
SpaceId: spaceId,
Filters: []*model.BlockContentDataviewFilter{
{
+ Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyLayout.String(),
Condition: model.BlockContentDataviewFilter_In,
Value: pbtypes.IntList([]int{
@@ -81,6 +84,18 @@ func (s *ObjectService) ListObjects(ctx context.Context, spaceId string, offset
int(model.ObjectType_participant),
}...),
},
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyType.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.String(typeId),
+ },
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyIsHidden.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.Bool(true),
+ },
},
Sorts: []*model.BlockContentDataviewSort{{
RelationKey: bundle.RelationKeyLastModifiedDate.String(),
@@ -268,11 +283,13 @@ func (s *ObjectService) ListTypes(ctx context.Context, spaceId string, offset in
SpaceId: spaceId,
Filters: []*model.BlockContentDataviewFilter{
{
+ Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyLayout.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Int64(int64(model.ObjectType_objectType)),
},
{
+ Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyIsHidden.String(),
Condition: model.BlockContentDataviewFilter_NotEqual,
Value: pbtypes.Bool(true),
@@ -340,6 +357,7 @@ func (s *ObjectService) ListTemplates(ctx context.Context, spaceId string, typeI
SpaceId: spaceId,
Filters: []*model.BlockContentDataviewFilter{
{
+ Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyUniqueKey.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("ot-template"),
@@ -362,6 +380,7 @@ func (s *ObjectService) ListTemplates(ctx context.Context, spaceId string, typeI
SpaceId: spaceId,
Filters: []*model.BlockContentDataviewFilter{
{
+ Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyType.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(templateTypeId),
diff --git a/core/api/internal/search/service.go b/core/api/internal/search/service.go
index ecd2408718..c325560e3a 100644
--- a/core/api/internal/search/service.go
+++ b/core/api/internal/search/service.go
@@ -52,9 +52,10 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
allResponses := make([]*pb.RpcObjectSearchResponse, 0, len(spaces))
for _, space := range spaces {
- // Resolve object type IDs per space, as they are unique per space
+ // Resolve template type and object type IDs per space, as they are unique per space
+ templateFilter := s.prepareTemplateFilter(space.Id)
typeFilters := s.prepareObjectTypeFilters(space.Id, request.Types)
- filters := s.combineFilters(model.BlockContentDataviewFilter_And, baseFilters, queryFilters, typeFilters)
+ filters := s.combineFilters(model.BlockContentDataviewFilter_And, baseFilters, templateFilter, queryFilters, typeFilters)
objResp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
SpaceId: space.Id,
@@ -113,9 +114,10 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
// Search retrieves a paginated list of objects from a specific space that match the search parameters.
func (s *SearchService) Search(ctx context.Context, spaceId string, request SearchRequest, offset int, limit int) (objects []object.Object, total int, hasMore bool, err error) {
baseFilters := s.prepareBaseFilters()
+ templateFilter := s.prepareTemplateFilter(spaceId)
queryFilters := s.prepareQueryFilter(request.Query)
typeFilters := s.prepareObjectTypeFilters(spaceId, request.Types)
- filters := s.combineFilters(model.BlockContentDataviewFilter_And, baseFilters, queryFilters, typeFilters)
+ filters := s.combineFilters(model.BlockContentDataviewFilter_And, baseFilters, templateFilter, queryFilters, typeFilters)
sorts := s.prepareSorts(request.Sort)
dateToSortAfter := sorts[0].RelationKey
@@ -194,6 +196,23 @@ func (s *SearchService) prepareBaseFilters() []*model.BlockContentDataviewFilter
}
}
+// prepareTemplateFilter returns a filter that excludes templates from the search results.
+func (s *SearchService) prepareTemplateFilter(spaceId string) []*model.BlockContentDataviewFilter {
+ typeId, err := util.ResolveUniqueKeyToTypeId(s.mw, spaceId, "ot-template")
+ if err != nil {
+ return nil
+ }
+
+ return []*model.BlockContentDataviewFilter{
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyType.String(),
+ Condition: model.BlockContentDataviewFilter_NotEqual,
+ Value: pbtypes.String(typeId),
+ },
+ }
+}
+
// prepareQueryFilter combines object name and snippet filters with an OR condition.
func (s *SearchService) prepareQueryFilter(searchQuery string) []*model.BlockContentDataviewFilter {
if searchQuery == "" {
@@ -243,7 +262,7 @@ func (s *SearchService) prepareObjectTypeFilters(spaceId string, objectTypes []s
nestedFilters = append(nestedFilters, &model.BlockContentDataviewFilter{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyType.String(),
- Condition: model.BlockContentDataviewFilter_Equal,
+ Condition: model.BlockContentDataviewFilter_NotEqual,
Value: pbtypes.String(typeId),
})
}
From fefb3b8b7d17d6d05c2007f2639802670f9cd744 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Mon, 17 Feb 2025 17:24:51 +0100
Subject: [PATCH 29/31] GO-4459: Fix tags in search test
---
core/api/internal/object/service.go | 17 +++++-----
core/api/internal/search/service_test.go | 40 ++++++++++++++++++++++++
2 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index acc74b2a5b..9fdc624405 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -521,19 +521,20 @@ func (s *ObjectService) getDetails(resp *pb.RpcObjectShowResponse) []Detail {
var details []Detail
for _, r := range linkedRelations {
- if _, isExcluded := excludeRelations[r.Key]; isExcluded {
+ key := r.Key
+ if _, isExcluded := excludeRelations[key]; isExcluded {
continue
}
- if val, ok := primaryDetailFields[r.Key]; ok {
- id, name := s.getRelation(r.Key, resp)
- format := relationFormatMap[r.Key]
+ if val, ok := primaryDetailFields[key]; ok {
+ id, name := s.getRelation(key, resp)
+ format := relationFormatMap[key]
details = append(details, Detail{
Id: id,
Details: map[string]interface{}{
"name": name,
"type": format,
- format: s.convertValue(val, format, r.Key, resp.ObjectView.Details),
+ format: s.convertValue(key, val, format, resp.ObjectView.Details),
},
})
}
@@ -563,7 +564,7 @@ func (s *ObjectService) getRelation(key string, resp *pb.RpcObjectShowResponse)
}
// convertValue converts a protobuf types.Value into a native Go value.
-func (s *ObjectService) convertValue(value *types.Value, format string, key string, details []*model.ObjectViewDetailsSet) interface{} {
+func (s *ObjectService) convertValue(key string, value *types.Value, format string, details []*model.ObjectViewDetailsSet) interface{} {
switch kind := value.Kind.(type) {
case *types.Value_NullValue:
return nil
@@ -592,13 +593,13 @@ func (s *ObjectService) convertValue(value *types.Value, format string, key stri
case *types.Value_StructValue:
m := make(map[string]interface{})
for k, v := range kind.StructValue.Fields {
- m[k] = s.convertValue(v, format, key, details)
+ m[k] = s.convertValue(key, v, format, details)
}
return m
case *types.Value_ListValue:
var list []interface{}
for _, v := range kind.ListValue.Values {
- list = append(list, s.convertValue(v, format, key, details))
+ list = append(list, s.convertValue(key, v, format, details))
}
if format == "select" || format == "multi_select" {
diff --git a/core/api/internal/search/service_test.go b/core/api/internal/search/service_test.go
index f7e3eb288a..2e0eac3ee8 100644
--- a/core/api/internal/search/service_test.go
+++ b/core/api/internal/search/service_test.go
@@ -375,6 +375,46 @@ func TestSearchService_GlobalSearch(t *testing.T) {
Error: &pb.RpcObjectSearchResponseError{Code: pb.RpcObjectSearchResponseError_NULL},
}).Twice()
+ // Mock tag-1 open
+ fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
+ SpaceId: mockedSpaceId,
+ ObjectId: mockedTagId1,
+ }).Return(&pb.RpcObjectShowResponse{
+ Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
+ ObjectView: &model.ObjectView{
+ Details: []*model.ObjectViewDetailsSet{
+ {
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyName.String(): pbtypes.String(mockedTagValue1),
+ bundle.RelationKeyRelationOptionColor.String(): pbtypes.String(mockedTagColor1),
+ },
+ },
+ },
+ },
+ },
+ }, nil).Once()
+
+ // Mock tag-2 open
+ fx.mwMock.On("ObjectShow", mock.Anything, &pb.RpcObjectShowRequest{
+ SpaceId: mockedSpaceId,
+ ObjectId: mockedTagId2,
+ }).Return(&pb.RpcObjectShowResponse{
+ Error: &pb.RpcObjectShowResponseError{Code: pb.RpcObjectShowResponseError_NULL},
+ ObjectView: &model.ObjectView{
+ Details: []*model.ObjectViewDetailsSet{
+ {
+ Details: &types.Struct{
+ Fields: map[string]*types.Value{
+ bundle.RelationKeyName.String(): pbtypes.String(mockedTagValue2),
+ bundle.RelationKeyRelationOptionColor.String(): pbtypes.String(mockedTagColor2),
+ },
+ },
+ },
+ },
+ },
+ }, nil).Once()
+
// when
objects, total, hasMore, err := fx.GlobalSearch(ctx, SearchRequest{Query: mockedSearchTerm, Types: []string{}, Sort: SortOptions{Direction: "desc", Timestamp: "last_modified_date"}}, offset, limit)
From 4df66f60ce3095ceab99dc3931b3855053e61521 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Thu, 20 Feb 2025 17:41:27 +0100
Subject: [PATCH 30/31] GO-4459: Add endpoint descriptions
---
core/api/docs/docs.go | 2 +-
core/api/docs/swagger.json | 2 +-
core/api/docs/swagger.yaml | 115 ++++++++++++++++
core/api/internal/auth/handler.go | 40 +++---
core/api/internal/export/handler.go | 27 ++--
core/api/internal/list/handler.go | 83 ++++++------
core/api/internal/object/handler.go | 196 +++++++++++++++-------------
core/api/internal/search/handler.go | 52 ++++----
core/api/internal/space/handler.go | 113 ++++++++--------
9 files changed, 383 insertions(+), 247 deletions(-)
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 01dd8e76e0..5698574b87 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -9,7 +9,7 @@ const docTemplate = `{
"components": {"schemas":{"auth.DisplayCodeResponse":{"properties":{"challenge_id":{"description":"The challenge id associated with the displayed code and needed to solve the challenge for token","example":"67647f5ecda913e9a2e11b26","type":"string"}},"type":"object"},"auth.TokenResponse":{"properties":{"app_key":{"description":"The permanent app key","example":"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=","type":"string"},"session_token":{"description":"The ephemeral session token","example":"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII","type":"string"}},"type":"object"},"export.ObjectExportResponse":{"properties":{"path":{"description":"The path the object was exported to","example":"/path/to/export","type":"string"}},"type":"object"},"object.Block":{"properties":{"align":{"description":"The alignment of the block","enum":["AlignLeft","AlignCenter","AlignRight","AlignJustify"],"example":"AlignLeft","type":"string"},"background_color":{"description":"The background color of the block","example":"red","type":"string"},"children_ids":{"description":"The ids of the block's children","example":["['6797ce8ecda913cde14b02dc']"],"items":{"type":"string"},"type":"array","uniqueItems":false},"file":{"$ref":"#/components/schemas/object.File"},"id":{"description":"The id of the block","example":"64394517de52ad5acb89c66c","type":"string"},"relation":{"$ref":"#/components/schemas/object.Relation"},"text":{"$ref":"#/components/schemas/object.Text"},"vertical_align":{"description":"The vertical alignment of the block","enum":["VerticalAlignTop","VerticalAlignMiddle","VerticalAlignBottom"],"example":"VerticalAlignTop","type":"string"}},"type":"object"},"object.CreateObjectRequest":{"properties":{"body":{"description":"The body of the object","example":"This is the body of the object. Markdown syntax is supported here.","type":"string"},"description":{"description":"The description of the object","example":"This is a description of the object.","type":"string"},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object_type_unique_key":{"description":"The unique key of the object type","example":"ot-page","type":"string"},"source":{"description":"The source url, only applicable for bookmarks","example":"https://bookmark-source.com","type":"string"},"template_id":{"description":"The id of the template to use","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"}},"type":"object"},"object.Detail":{"properties":{"details":{"additionalProperties":{},"description":"The details","type":"object"},"id":{"description":"The id of the detail","enum":["last_modified_date","last_modified_by","created_date","created_by","last_opened_date","tags"],"example":"last_modified_date","type":"string"}},"type":"object"},"object.File":{"description":"The file of the block, if applicable","properties":{"added_at":{"description":"The added at of the file","type":"integer"},"hash":{"description":"The hash of the file","type":"string"},"mime":{"description":"The mime of the file","type":"string"},"name":{"description":"The name of the file","type":"string"},"size":{"description":"The size of the file","type":"integer"},"state":{"description":"The state of the file","type":"string"},"style":{"description":"The style of the file","type":"string"},"target_object_id":{"description":"The target object id of the file","type":"string"},"type":{"description":"The type of the file","type":"string"}},"type":"object"},"object.Object":{"description":"The object","properties":{"blocks":{"description":"The blocks of the object","items":{"$ref":"#/components/schemas/object.Block"},"type":"array","uniqueItems":false},"details":{"description":"The details of the object","items":{"$ref":"#/components/schemas/object.Detail"},"type":"array","uniqueItems":false},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"id":{"description":"The id of the object","example":"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ","type":"string"},"layout":{"description":"The layout of the object","example":"basic","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object":{"description":"The data model of the object","example":"object","type":"string"},"root_id":{"description":"The id of the object's root","example":"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u","type":"string"},"snippet":{"description":"The snippet of the object, especially important for notes as they don't have a name","example":"The beginning of the object body...","type":"string"},"space_id":{"description":"The id of the space the object is in","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"object.ObjectResponse":{"properties":{"object":{"$ref":"#/components/schemas/object.Object"}},"type":"object"},"object.Relation":{"description":"The relation of the block, if applicable","properties":{"id":{"type":"string"}},"type":"object"},"object.Template":{"description":"The template","properties":{"icon":{"description":"The icon of the template","example":"📄","type":"string"},"id":{"description":"The id of the template","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"},"name":{"description":"The name of the template","example":"My template","type":"string"},"object":{"description":"The data model of the object","example":"template","type":"string"}},"type":"object"},"object.TemplateResponse":{"properties":{"template":{"$ref":"#/components/schemas/object.Template"}},"type":"object"},"object.Text":{"description":"The text of the block, if applicable","properties":{"checked":{"description":"Whether the text is checked","example":true,"type":"boolean"},"color":{"description":"The color of the text","example":"red","type":"string"},"icon":{"description":"The icon of the text","example":"📄","type":"string"},"style":{"description":"The style of the text","enum":["Paragraph","Header1","Header2","Header3","Header4","Quote","Code","Title","Checkbox","Marked","Numbered","Toggle","Description","Callout"],"example":"Paragraph","type":"string"},"text":{"description":"The text","example":"Some text...","type":"string"}},"type":"object"},"object.Type":{"description":"The type of the object","properties":{"icon":{"description":"The icon of the type","example":"📄","type":"string"},"id":{"description":"The id of the type","example":"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu","type":"string"},"name":{"description":"The name of the type","example":"Page","type":"string"},"object":{"description":"The data model of the object","example":"type","type":"string"},"recommended_layout":{"description":"The recommended layout of the type","example":"todo","type":"string"},"unique_key":{"description":"The unique key of the type","example":"ot-page","type":"string"}},"type":"object"},"object.TypeResponse":{"properties":{"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"pagination.PaginatedResponse-object_Object":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Object"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Template":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Template"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Type":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Type"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Member":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Member"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Space":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Space"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginationMeta":{"description":"The pagination metadata for the response","properties":{"has_more":{"description":"Indicates if there are more items available beyond the current result set","example":true,"type":"boolean"},"limit":{"description":"The maximum number of items returned in the result set","example":100,"type":"integer"},"offset":{"description":"The number of items skipped before starting to collect the result set","example":0,"type":"integer"},"total":{"description":"The total number of items available for the endpoint","example":1024,"type":"integer"}},"type":"object"},"search.SearchRequest":{"properties":{"query":{"description":"The search term to look for in object names and snippets","example":"test","type":"string"},"sort":{"$ref":"#/components/schemas/search.SortOptions"},"types":{"description":"The types of objects to search for, specified by unique key or ID","example":["ot-note","ot-page","ot-678043f0cda9133be777049f","bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"],"items":{"type":"string"},"type":"array","uniqueItems":false}},"type":"object"},"search.SortOptions":{"description":"The sorting criteria and direction for the search results","properties":{"direction":{"default":"desc","description":"The direction to sort the search results","enum":["asc","desc"],"type":"string"},"timestamp":{"default":"last_modified_date","description":"The timestamp to sort the search results by","enum":["created_date","last_modified_date","last_opened_date"],"type":"string"}},"type":"object"},"space.CreateSpaceRequest":{"properties":{"name":{"description":"The name of the space","example":"New Space","type":"string"}},"type":"object"},"space.Member":{"description":"The member","properties":{"global_name":{"description":"The global name of the member in the network","example":"john.any","type":"string"},"icon":{"description":"The icon of the member","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100","type":"string"},"id":{"description":"The profile object id of the member","example":"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ","type":"string"},"identity":{"description":"The identity of the member in the network","example":"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ","type":"string"},"name":{"description":"The name of the member","example":"John Doe","type":"string"},"object":{"description":"The data model of the object","example":"member","type":"string"},"role":{"description":"The role of the member","enum":["Reader","Writer","Owner","NoPermission"],"example":"Owner","type":"string"}},"type":"object"},"space.MemberResponse":{"properties":{"member":{"$ref":"#/components/schemas/space.Member"}},"type":"object"},"space.Space":{"description":"The space","properties":{"account_space_id":{"description":"The id of the account space","example":"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1","type":"string"},"analytics_id":{"description":"The analytics id of the account","example":"624aecdd-4797-4611-9d61-a2ae5f53cf1c","type":"string"},"archive_object_id":{"description":"The id of the archive object","example":"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri","type":"string"},"device_id":{"description":"The id of the device","example":"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF","type":"string"},"gateway_url":{"description":"The gateway url to serve files and media","example":"http://127.0.0.1:31006","type":"string"},"home_object_id":{"description":"The id of the home object","example":"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya","type":"string"},"icon":{"description":"The icon of the space","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay","type":"string"},"id":{"description":"The id of the space","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"local_storage_path":{"description":"The local storage path of the account","example":"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha","type":"string"},"marketplace_workspace_id":{"description":"The id of the marketplace workspace","example":"_anytype_marketplace","type":"string"},"name":{"description":"The name of the space","example":"My Space","type":"string"},"network_id":{"description":"The network id of the space","example":"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU","type":"string"},"object":{"description":"The data model of the object","example":"space","type":"string"},"profile_object_id":{"description":"The id of the profile object","example":"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4","type":"string"},"space_view_id":{"description":"The id of the space view","example":"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy","type":"string"},"tech_space_id":{"description":"The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself","example":"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1","type":"string"},"timezone":{"description":"The timezone of the account","example":"","type":"string"},"widgets_id":{"description":"The id of the widgets","example":"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva","type":"string"},"workspace_object_id":{"description":"The id of the workspace object","example":"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y","type":"string"}},"type":"object"},"space.SpaceResponse":{"properties":{"space":{"$ref":"#/components/schemas/space.Space"}},"type":"object"},"util.ForbiddenError":{"properties":{"error":{"properties":{"message":{"example":"Forbidden","type":"string"}},"type":"object"}},"type":"object"},"util.NotFoundError":{"properties":{"error":{"properties":{"message":{"example":"Resource not found","type":"string"}},"type":"object"}},"type":"object"},"util.RateLimitError":{"properties":{"error":{"properties":{"message":{"example":"Rate limit exceeded","type":"string"}},"type":"object"}},"type":"object"},"util.ServerError":{"properties":{"error":{"properties":{"message":{"example":"Internal server error","type":"string"}},"type":"object"}},"type":"object"},"util.UnauthorizedError":{"properties":{"error":{"properties":{"message":{"example":"Unauthorized","type":"string"}},"type":"object"}},"type":"object"},"util.ValidationError":{"properties":{"error":{"properties":{"message":{"example":"Bad request","type":"string"}},"type":"object"}},"type":"object"}},"securitySchemes":{"bearerauth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"}}},
"info": {"contact":{"email":"support@anytype.io","name":"Anytype Support","url":"https://anytype.io/contact"},"description":"{{escape .Description}}","license":{"name":"Any Source Available License 1.0","url":"https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md"},"termsOfService":"https://anytype.io/terms_of_use","title":"{{.Title}}","version":"{{.Version}}"},
"externalDocs": {"description":"OpenAPI","url":"https://swagger.io/resources/open-api/"},
- "paths": {"/auth/display_code":{"post":{"parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
+ "paths": {"/auth/display_code":{"post":{"description":"This endpoint initiates a secure authentication flow by generating a new challenge. Clients must supply the name of the application (via a query parameter) that is requesting authentication. On success, the service returns a unique challenge ID. This challenge ID must then be used with the token endpoint (see below) to solve the challenge and retrieve an authentication token. In essence, this endpoint “boots up” the login process and is the first step in a multi-phase authentication sequence.","parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"description":"After receiving a challenge ID from the display_code endpoint, the client calls this endpoint to provide the corresponding 4-digit code (also via a query parameter) along with the challenge ID. The endpoint verifies that the challenge solution is correct and, if it is, returns an ephemeral session token together with a permanent app key. These tokens are then used in subsequent API requests to authorize access. This endpoint is central to ensuring that only properly authenticated sessions can access further resources.","parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"description":"This endpoint executes a global search over every space the user has access to. It accepts pagination parameters (offset and limit) and a JSON body containing search criteria. The criteria include a search query string, an optional list of object types, and sort options (e.g. ascending/descending by creation, modification, or last opened dates). Internally, the endpoint aggregates results from each space, merges and sorts them (after last modified date by default), and returns a unified, paginated list of objects that match the search parameters.","parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"description":"Retrieves a paginated list of all spaces that are accessible by the authenticated user. Each space record contains detailed information such as the space ID, name, icon (derived either from an emoji or image URL), and additional metadata. This endpoint is key to displaying a user’s workspaces.","parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"description":"Creates a new workspace (or space) based on a supplied name in the JSON request body. The endpoint is subject to rate limiting and automatically applies default configurations such as generating a random icon and initializing the workspace with default settings (for example, a default dashboard or home page). On success, the new space’s full metadata is returned, enabling the client to immediately switch context to the new space.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"description":"Fetches full details about a single space identified by its space ID. The response includes metadata such as the space name, icon, and various workspace IDs (home, archive, profile, etc.). This detailed view supports use cases such as displaying space-specific settings.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"description":"Returns a paginated list of members belonging to the specified space. Each member record includes the member’s profile ID, name, icon (which may be derived from an emoji or image), network identity, global name, and role (e.g. Reader, Writer, Owner). This endpoint supports collaborative features by allowing clients to show who is in a space and manage access rights.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"description":"Fetches detailed information about a single member within a space. The endpoint returns the member’s identifier, name, icon, identity, global name, and role. This is useful for user profile pages, permission management, and displaying member-specific information in collaborative environments.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"description":"Retrieves a paginated list of objects in the given space. The endpoint takes query parameters for pagination (offset and limit) and returns detailed data about each object including its ID, name, icon, type information, a snippet of the content (if applicable), layout, space ID, blocks and details. It is intended for building views where users can see all objects in a space at a glance.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"description":"Creates a new object in the specified space using a JSON payload. The creation process is subject to rate limiting. The payload must include key details such as the object name, icon, description, body content (which may support Markdown), source URL (required for bookmark objects), template identifier, and the unique key for the object type. Post-creation, additional operations (like setting featured relations or fetching bookmark metadata) may occur. The endpoint then returns the full object data, ready for further interactions.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"description":"This endpoint “deletes” an object by marking it as archived. The deletion process is performed safely and is subject to rate limiting. It returns the object’s details after it has been archived. Proper error handling is in place for situations such as when the object isn’t found or the deletion cannot be performed because of permission issues.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"description":"Fetches the full details of a single object identified by the object ID within the specified space. The response includes not only basic metadata (ID, name, icon, type) but also the complete set of blocks (which may include text, files, and relations) and extra details (such as timestamps and linked member information). This endpoint is essential when a client needs to render or edit the full object view.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"description":"This endpoint exports a single object from the specified space into a desired format. The export format is provided as a path parameter (currently supporting “markdown” and “protobuf”), and clients can optionally specify an export path in the request body. The endpoint calls an export service which converts the object’s content into the requested format and returns the file path where the exported data is stored. It is useful for data backup, sharing, or further processing.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"description":"This endpoint performs a focused search within a single space (specified by the space_id path parameter). Like the global search, it accepts pagination parameters and a JSON payload containing the search query, object types, and sorting preferences. The search is limited to the provided space and returns a list of objects that match the query. This allows clients to implement space‑specific filtering without having to process extraneous results.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"description":"This endpoint retrieves a paginated list of object types (e.g. 'Page', 'Note', 'Task') available within the specified space. Each type’s record includes its unique identifier, unique key, display name, icon, and a recommended layout. Clients use this information when offering choices for object creation or for filtering objects by type.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"description":"Fetches detailed information about one specific object type by its ID. This includes the type’s unique key, name, icon, and recommended layout. This detailed view assists clients in understanding the expected structure and style for objects of that type and in guiding the user interface (such as displaying appropriate icons or layout hints).","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"description":"This endpoint returns a paginated list of templates that are associated with a specific object type within a space. Templates provide pre‑configured structures for creating new objects. Each template record contains its identifier, name, and icon, so that clients can offer users a selection of templates when creating objects.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"description":"Fetches full details for one template associated with a particular object type in a space. The response provides the template’s identifier, name, icon, and any other relevant metadata. This endpoint is useful when a client needs to preview or apply a template to prefill object creation fields.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"description":"Returns a paginated list of objects that are associated with a specific list (or collection) within a space. This endpoint helps clients to manage grouped objects (for example, tasks within a list) by returning detailed object information for each item of the list.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"description":"Enables clients to add one or more objects to a specific list by submitting a JSON array of object IDs. Upon success, the endpoint returns a confirmation message. This endpoint is vital for building user interfaces that allow drag‑and‑drop or multi‑select additions to collections.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"description":"Removes a given object from the specified list in a space. The endpoint takes the space, list, and object identifiers as path parameters. It's subject to rate limiting and returns a success message on completion. It is used for dynamically managing collections without affecting the underlying object data.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
"openapi": "3.1.0",
"servers": [
{"url":"http://localhost:31009/v1"}
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index 3247b1acfb..903f69158a 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -2,7 +2,7 @@
"components": {"schemas":{"auth.DisplayCodeResponse":{"properties":{"challenge_id":{"description":"The challenge id associated with the displayed code and needed to solve the challenge for token","example":"67647f5ecda913e9a2e11b26","type":"string"}},"type":"object"},"auth.TokenResponse":{"properties":{"app_key":{"description":"The permanent app key","example":"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=","type":"string"},"session_token":{"description":"The ephemeral session token","example":"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII","type":"string"}},"type":"object"},"export.ObjectExportResponse":{"properties":{"path":{"description":"The path the object was exported to","example":"/path/to/export","type":"string"}},"type":"object"},"object.Block":{"properties":{"align":{"description":"The alignment of the block","enum":["AlignLeft","AlignCenter","AlignRight","AlignJustify"],"example":"AlignLeft","type":"string"},"background_color":{"description":"The background color of the block","example":"red","type":"string"},"children_ids":{"description":"The ids of the block's children","example":["['6797ce8ecda913cde14b02dc']"],"items":{"type":"string"},"type":"array","uniqueItems":false},"file":{"$ref":"#/components/schemas/object.File"},"id":{"description":"The id of the block","example":"64394517de52ad5acb89c66c","type":"string"},"relation":{"$ref":"#/components/schemas/object.Relation"},"text":{"$ref":"#/components/schemas/object.Text"},"vertical_align":{"description":"The vertical alignment of the block","enum":["VerticalAlignTop","VerticalAlignMiddle","VerticalAlignBottom"],"example":"VerticalAlignTop","type":"string"}},"type":"object"},"object.CreateObjectRequest":{"properties":{"body":{"description":"The body of the object","example":"This is the body of the object. Markdown syntax is supported here.","type":"string"},"description":{"description":"The description of the object","example":"This is a description of the object.","type":"string"},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object_type_unique_key":{"description":"The unique key of the object type","example":"ot-page","type":"string"},"source":{"description":"The source url, only applicable for bookmarks","example":"https://bookmark-source.com","type":"string"},"template_id":{"description":"The id of the template to use","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"}},"type":"object"},"object.Detail":{"properties":{"details":{"additionalProperties":{},"description":"The details","type":"object"},"id":{"description":"The id of the detail","enum":["last_modified_date","last_modified_by","created_date","created_by","last_opened_date","tags"],"example":"last_modified_date","type":"string"}},"type":"object"},"object.File":{"description":"The file of the block, if applicable","properties":{"added_at":{"description":"The added at of the file","type":"integer"},"hash":{"description":"The hash of the file","type":"string"},"mime":{"description":"The mime of the file","type":"string"},"name":{"description":"The name of the file","type":"string"},"size":{"description":"The size of the file","type":"integer"},"state":{"description":"The state of the file","type":"string"},"style":{"description":"The style of the file","type":"string"},"target_object_id":{"description":"The target object id of the file","type":"string"},"type":{"description":"The type of the file","type":"string"}},"type":"object"},"object.Object":{"description":"The object","properties":{"blocks":{"description":"The blocks of the object","items":{"$ref":"#/components/schemas/object.Block"},"type":"array","uniqueItems":false},"details":{"description":"The details of the object","items":{"$ref":"#/components/schemas/object.Detail"},"type":"array","uniqueItems":false},"icon":{"description":"The icon of the object","example":"📄","type":"string"},"id":{"description":"The id of the object","example":"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ","type":"string"},"layout":{"description":"The layout of the object","example":"basic","type":"string"},"name":{"description":"The name of the object","example":"My object","type":"string"},"object":{"description":"The data model of the object","example":"object","type":"string"},"root_id":{"description":"The id of the object's root","example":"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u","type":"string"},"snippet":{"description":"The snippet of the object, especially important for notes as they don't have a name","example":"The beginning of the object body...","type":"string"},"space_id":{"description":"The id of the space the object is in","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"object.ObjectResponse":{"properties":{"object":{"$ref":"#/components/schemas/object.Object"}},"type":"object"},"object.Relation":{"description":"The relation of the block, if applicable","properties":{"id":{"type":"string"}},"type":"object"},"object.Template":{"description":"The template","properties":{"icon":{"description":"The icon of the template","example":"📄","type":"string"},"id":{"description":"The id of the template","example":"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge","type":"string"},"name":{"description":"The name of the template","example":"My template","type":"string"},"object":{"description":"The data model of the object","example":"template","type":"string"}},"type":"object"},"object.TemplateResponse":{"properties":{"template":{"$ref":"#/components/schemas/object.Template"}},"type":"object"},"object.Text":{"description":"The text of the block, if applicable","properties":{"checked":{"description":"Whether the text is checked","example":true,"type":"boolean"},"color":{"description":"The color of the text","example":"red","type":"string"},"icon":{"description":"The icon of the text","example":"📄","type":"string"},"style":{"description":"The style of the text","enum":["Paragraph","Header1","Header2","Header3","Header4","Quote","Code","Title","Checkbox","Marked","Numbered","Toggle","Description","Callout"],"example":"Paragraph","type":"string"},"text":{"description":"The text","example":"Some text...","type":"string"}},"type":"object"},"object.Type":{"description":"The type of the object","properties":{"icon":{"description":"The icon of the type","example":"📄","type":"string"},"id":{"description":"The id of the type","example":"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu","type":"string"},"name":{"description":"The name of the type","example":"Page","type":"string"},"object":{"description":"The data model of the object","example":"type","type":"string"},"recommended_layout":{"description":"The recommended layout of the type","example":"todo","type":"string"},"unique_key":{"description":"The unique key of the type","example":"ot-page","type":"string"}},"type":"object"},"object.TypeResponse":{"properties":{"type":{"$ref":"#/components/schemas/object.Type"}},"type":"object"},"pagination.PaginatedResponse-object_Object":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Object"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Template":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Template"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-object_Type":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/object.Type"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Member":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Member"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginatedResponse-space_Space":{"properties":{"data":{"description":"The list of items in the current result set","items":{"$ref":"#/components/schemas/space.Space"},"type":"array","uniqueItems":false},"pagination":{"$ref":"#/components/schemas/pagination.PaginationMeta"}},"type":"object"},"pagination.PaginationMeta":{"description":"The pagination metadata for the response","properties":{"has_more":{"description":"Indicates if there are more items available beyond the current result set","example":true,"type":"boolean"},"limit":{"description":"The maximum number of items returned in the result set","example":100,"type":"integer"},"offset":{"description":"The number of items skipped before starting to collect the result set","example":0,"type":"integer"},"total":{"description":"The total number of items available for the endpoint","example":1024,"type":"integer"}},"type":"object"},"search.SearchRequest":{"properties":{"query":{"description":"The search term to look for in object names and snippets","example":"test","type":"string"},"sort":{"$ref":"#/components/schemas/search.SortOptions"},"types":{"description":"The types of objects to search for, specified by unique key or ID","example":["ot-note","ot-page","ot-678043f0cda9133be777049f","bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"],"items":{"type":"string"},"type":"array","uniqueItems":false}},"type":"object"},"search.SortOptions":{"description":"The sorting criteria and direction for the search results","properties":{"direction":{"default":"desc","description":"The direction to sort the search results","enum":["asc","desc"],"type":"string"},"timestamp":{"default":"last_modified_date","description":"The timestamp to sort the search results by","enum":["created_date","last_modified_date","last_opened_date"],"type":"string"}},"type":"object"},"space.CreateSpaceRequest":{"properties":{"name":{"description":"The name of the space","example":"New Space","type":"string"}},"type":"object"},"space.Member":{"description":"The member","properties":{"global_name":{"description":"The global name of the member in the network","example":"john.any","type":"string"},"icon":{"description":"The icon of the member","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100","type":"string"},"id":{"description":"The profile object id of the member","example":"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ","type":"string"},"identity":{"description":"The identity of the member in the network","example":"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ","type":"string"},"name":{"description":"The name of the member","example":"John Doe","type":"string"},"object":{"description":"The data model of the object","example":"member","type":"string"},"role":{"description":"The role of the member","enum":["Reader","Writer","Owner","NoPermission"],"example":"Owner","type":"string"}},"type":"object"},"space.MemberResponse":{"properties":{"member":{"$ref":"#/components/schemas/space.Member"}},"type":"object"},"space.Space":{"description":"The space","properties":{"account_space_id":{"description":"The id of the account space","example":"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1","type":"string"},"analytics_id":{"description":"The analytics id of the account","example":"624aecdd-4797-4611-9d61-a2ae5f53cf1c","type":"string"},"archive_object_id":{"description":"The id of the archive object","example":"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri","type":"string"},"device_id":{"description":"The id of the device","example":"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF","type":"string"},"gateway_url":{"description":"The gateway url to serve files and media","example":"http://127.0.0.1:31006","type":"string"},"home_object_id":{"description":"The id of the home object","example":"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya","type":"string"},"icon":{"description":"The icon of the space","example":"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay","type":"string"},"id":{"description":"The id of the space","example":"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1","type":"string"},"local_storage_path":{"description":"The local storage path of the account","example":"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha","type":"string"},"marketplace_workspace_id":{"description":"The id of the marketplace workspace","example":"_anytype_marketplace","type":"string"},"name":{"description":"The name of the space","example":"My Space","type":"string"},"network_id":{"description":"The network id of the space","example":"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU","type":"string"},"object":{"description":"The data model of the object","example":"space","type":"string"},"profile_object_id":{"description":"The id of the profile object","example":"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4","type":"string"},"space_view_id":{"description":"The id of the space view","example":"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy","type":"string"},"tech_space_id":{"description":"The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself","example":"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1","type":"string"},"timezone":{"description":"The timezone of the account","example":"","type":"string"},"widgets_id":{"description":"The id of the widgets","example":"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva","type":"string"},"workspace_object_id":{"description":"The id of the workspace object","example":"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y","type":"string"}},"type":"object"},"space.SpaceResponse":{"properties":{"space":{"$ref":"#/components/schemas/space.Space"}},"type":"object"},"util.ForbiddenError":{"properties":{"error":{"properties":{"message":{"example":"Forbidden","type":"string"}},"type":"object"}},"type":"object"},"util.NotFoundError":{"properties":{"error":{"properties":{"message":{"example":"Resource not found","type":"string"}},"type":"object"}},"type":"object"},"util.RateLimitError":{"properties":{"error":{"properties":{"message":{"example":"Rate limit exceeded","type":"string"}},"type":"object"}},"type":"object"},"util.ServerError":{"properties":{"error":{"properties":{"message":{"example":"Internal server error","type":"string"}},"type":"object"}},"type":"object"},"util.UnauthorizedError":{"properties":{"error":{"properties":{"message":{"example":"Unauthorized","type":"string"}},"type":"object"}},"type":"object"},"util.ValidationError":{"properties":{"error":{"properties":{"message":{"example":"Bad request","type":"string"}},"type":"object"}},"type":"object"}},"securitySchemes":{"bearerauth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"}}},
"info": {"contact":{"email":"support@anytype.io","name":"Anytype Support","url":"https://anytype.io/contact"},"description":"This API allows interaction with Anytype resources such as spaces, objects and types.","license":{"name":"Any Source Available License 1.0","url":"https://github.com/anyproto/anytype-ts/blob/main/LICENSE.md"},"termsOfService":"https://anytype.io/terms_of_use","title":"Anytype API","version":"1.0"},
"externalDocs": {"description":"OpenAPI","url":"https://swagger.io/resources/open-api/"},
- "paths": {"/auth/display_code":{"post":{"parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
+ "paths": {"/auth/display_code":{"post":{"description":"This endpoint initiates a secure authentication flow by generating a new challenge. Clients must supply the name of the application (via a query parameter) that is requesting authentication. On success, the service returns a unique challenge ID. This challenge ID must then be used with the token endpoint (see below) to solve the challenge and retrieve an authentication token. In essence, this endpoint “boots up” the login process and is the first step in a multi-phase authentication sequence.","parameters":[{"description":"App name requesting the challenge","in":"query","name":"app_name","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.DisplayCodeResponse"}}},"description":"Challenge ID"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Start new challenge","tags":["auth"]}},"/auth/token":{"post":{"description":"After receiving a challenge ID from the display_code endpoint, the client calls this endpoint to provide the corresponding 4-digit code (also via a query parameter) along with the challenge ID. The endpoint verifies that the challenge solution is correct and, if it is, returns an ephemeral session token together with a permanent app key. These tokens are then used in subsequent API requests to authorize access. This endpoint is central to ensuring that only properly authenticated sessions can access further resources.","parameters":[{"description":"Challenge ID","in":"query","name":"challenge_id","required":true,"schema":{"type":"string"}},{"description":"4-digit code retrieved from Anytype Desktop app","in":"query","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth.TokenResponse"}}},"description":"Authentication token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Invalid input"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"summary":"Retrieve token","tags":["auth"]}},"/search":{"post":{"description":"This endpoint executes a global search over every space the user has access to. It accepts pagination parameters (offset and limit) and a JSON body containing search criteria. The criteria include a search query string, an optional list of object types, and sort options (e.g. ascending/descending by creation, modification, or last opened dates). Internally, the endpoint aggregates results from each space, merges and sorts them (after last modified date by default), and returns a unified, paginated list of objects that match the search parameters.","parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects across all spaces","tags":["search"]}},"/spaces":{"get":{"description":"Retrieves a paginated list of all spaces that are accessible by the authenticated user. Each space record contains detailed information such as the space ID, name, icon (derived either from an emoji or image URL), and additional metadata. This endpoint is key to displaying a user’s workspaces.","parameters":[{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Space"}}},"description":"List of spaces"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List spaces","tags":["spaces"]},"post":{"description":"Creates a new workspace (or space) based on a supplied name in the JSON request body. The endpoint is subject to rate limiting and automatically applies default configurations such as generating a random icon and initializing the workspace with default settings (for example, a default dashboard or home page). On success, the new space’s full metadata is returned, enabling the client to immediately switch context to the new space.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.CreateSpaceRequest"}}},"description":"Space to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space created successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create space","tags":["spaces"]}},"/spaces/{space_id}":{"get":{"description":"Fetches full details about a single space identified by its space ID. The response includes metadata such as the space name, icon, and various workspace IDs (home, archive, profile, etc.). This detailed view supports use cases such as displaying space-specific settings.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.SpaceResponse"}}},"description":"Space"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Space not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get space","tags":["spaces"]}},"/spaces/{space_id}/members":{"get":{"description":"Returns a paginated list of members belonging to the specified space. Each member record includes the member’s profile ID, name, icon (which may be derived from an emoji or image), network identity, global name, and role (e.g. Reader, Writer, Owner). This endpoint supports collaborative features by allowing clients to show who is in a space and manage access rights.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-space_Member"}}},"description":"List of members"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List members","tags":["spaces"]}},"/spaces/{space_id}/members/{member_id}":{"get":{"description":"Fetches detailed information about a single member within a space. The endpoint returns the member’s identifier, name, icon, identity, global name, and role. This is useful for user profile pages, permission management, and displaying member-specific information in collaborative environments.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Member ID","in":"path","name":"member_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/space.MemberResponse"}}},"description":"Member"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Member not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get member","tags":["spaces"]}},"/spaces/{space_id}/objects":{"get":{"description":"Retrieves a paginated list of objects in the given space. The endpoint takes query parameters for pagination (offset and limit) and returns detailed data about each object including its ID, name, icon, type information, a snippet of the content (if applicable), layout, space ID, blocks and details. It is intended for building views where users can see all objects in a space at a glance.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List objects","tags":["objects"]},"post":{"description":"Creates a new object in the specified space using a JSON payload. The creation process is subject to rate limiting. The payload must include key details such as the object name, icon, description, body content (which may support Markdown), source URL (required for bookmark objects), template identifier, and the unique key for the object type. Post-creation, additional operations (like setting featured relations or fetching bookmark metadata) may occur. The endpoint then returns the full object data, ready for further interactions.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.CreateObjectRequest"}}},"description":"Object to create","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The created object"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Create object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}":{"delete":{"description":"This endpoint “deletes” an object by marking it as archived. The deletion process is performed safely and is subject to rate limiting. It returns the object’s details after it has been archived. Proper error handling is in place for situations such as when the object isn’t found or the deletion cannot be performed because of permission issues.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The deleted object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"423":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.RateLimitError"}}},"description":"Rate limit exceeded"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Delete object","tags":["objects"]},"get":{"description":"Fetches the full details of a single object identified by the object ID within the specified space. The response includes not only basic metadata (ID, name, icon, type) but also the complete set of blocks (which may include text, files, and relations) and extra details (such as timestamps and linked member information). This endpoint is essential when a client needs to render or edit the full object view.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.ObjectResponse"}}},"description":"The requested object"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get object","tags":["objects"]}},"/spaces/{space_id}/objects/{object_id}/export/{format}":{"post":{"description":"This endpoint exports a single object from the specified space into a desired format. The export format is provided as a path parameter (currently supporting “markdown” and “protobuf”), and clients can optionally specify an export path in the request body. The endpoint calls an export service which converts the object’s content into the requested format and returns the file path where the exported data is stored. It is useful for data backup, sharing, or further processing.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}},{"description":"Export format","in":"path","name":"format","required":true,"schema":{"enum":["markdown","protobuf"],"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/export.ObjectExportResponse"}}},"description":"Object exported successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Export object","tags":["export"]}},"/spaces/{space_id}/search":{"post":{"description":"This endpoint performs a focused search within a single space (specified by the space_id path parameter). Like the global search, it accepts pagination parameters and a JSON payload containing the search query, object types, and sorting preferences. The search is limited to the provided space and returns a list of objects that match the query. This allows clients to implement space‑specific filtering without having to process extraneous results.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search.SearchRequest"}}},"description":"Search parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Search objects within a space","tags":["search"]}},"/spaces/{space_id}/types":{"get":{"description":"This endpoint retrieves a paginated list of object types (e.g. 'Page', 'Note', 'Task') available within the specified space. Each type’s record includes its unique identifier, unique key, display name, icon, and a recommended layout. Clients use this information when offering choices for object creation or for filtering objects by type.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Type"}}},"description":"List of types"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List types","tags":["types"]}},"/spaces/{space_id}/types/{type_id}":{"get":{"description":"Fetches detailed information about one specific object type by its ID. This includes the type’s unique key, name, icon, and recommended layout. This detailed view assists clients in understanding the expected structure and style for objects of that type and in guiding the user interface (such as displaying appropriate icons or layout hints).","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TypeResponse"}}},"description":"The requested type"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get type","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates":{"get":{"description":"This endpoint returns a paginated list of templates that are associated with a specific object type within a space. Templates provide pre‑configured structures for creating new objects. Each template record contains its identifier, name, and icon, so that clients can offer users a selection of templates when creating objects.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Template"}}},"description":"List of templates"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"List templates","tags":["types"]}},"/spaces/{space_id}/types/{type_id}/templates/{template_id}":{"get":{"description":"Fetches full details for one template associated with a particular object type in a space. The response provides the template’s identifier, name, icon, and any other relevant metadata. This endpoint is useful when a client needs to preview or apply a template to prefill object creation fields.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"Type ID","in":"path","name":"type_id","required":true,"schema":{"type":"string"}},{"description":"Template ID","in":"path","name":"template_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/object.TemplateResponse"}}},"description":"The requested template"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Resource not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get template","tags":["types"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects":{"get":{"description":"Returns a paginated list of objects that are associated with a specific list (or collection) within a space. This endpoint helps clients to manage grouped objects (for example, tasks within a list) by returning detailed object information for each item of the list.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"The number of items to skip before starting to collect the result set","in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"description":"The number of items to return","in":"query","name":"limit","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pagination.PaginatedResponse-object_Object"}}},"description":"List of objects"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Get objects in list","tags":["lists"]},"post":{"description":"Enables clients to add one or more objects to a specific list by submitting a JSON array of object IDs. Upon success, the endpoint returns a confirmation message. This endpoint is vital for building user interfaces that allow drag‑and‑drop or multi‑select additions to collections.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array"}}},"description":"List of object IDs","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects added successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Add objects to list","tags":["lists"]}},"/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}":{"delete":{"description":"Removes a given object from the specified list in a space. The endpoint takes the space, list, and object identifiers as path parameters. It's subject to rate limiting and returns a success message on completion. It is used for dynamically managing collections without affecting the underlying object data.","parameters":[{"description":"Space ID","in":"path","name":"space_id","required":true,"schema":{"type":"string"}},{"description":"List ID","in":"path","name":"list_id","required":true,"schema":{"type":"string"}},{"description":"Object ID","in":"path","name":"object_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Objects removed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ValidationError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.UnauthorizedError"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.NotFoundError"}}},"description":"Not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/util.ServerError"}}},"description":"Internal server error"}},"security":[{"bearerauth":[]}],"summary":"Remove object from list","tags":["lists"]}}},
"openapi": "3.1.0",
"servers": [
{"url":"http://localhost:31009/v1"}
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 2c3ff7a8e8..13e0363eba 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -638,6 +638,13 @@ openapi: 3.1.0
paths:
/auth/display_code:
post:
+ description: This endpoint initiates a secure authentication flow by generating
+ a new challenge. Clients must supply the name of the application (via a query
+ parameter) that is requesting authentication. On success, the service returns
+ a unique challenge ID. This challenge ID must then be used with the token
+ endpoint (see below) to solve the challenge and retrieve an authentication
+ token. In essence, this endpoint “boots up” the login process and is the first
+ step in a multi-phase authentication sequence.
parameters:
- description: App name requesting the challenge
in: query
@@ -674,6 +681,13 @@ paths:
- auth
/auth/token:
post:
+ description: After receiving a challenge ID from the display_code endpoint,
+ the client calls this endpoint to provide the corresponding 4-digit code (also
+ via a query parameter) along with the challenge ID. The endpoint verifies
+ that the challenge solution is correct and, if it is, returns an ephemeral
+ session token together with a permanent app key. These tokens are then used
+ in subsequent API requests to authorize access. This endpoint is central to
+ ensuring that only properly authenticated sessions can access further resources.
parameters:
- description: Challenge ID
in: query
@@ -716,6 +730,14 @@ paths:
- auth
/search:
post:
+ description: This endpoint executes a global search over every space the user
+ has access to. It accepts pagination parameters (offset and limit) and a JSON
+ body containing search criteria. The criteria include a search query string,
+ an optional list of object types, and sort options (e.g. ascending/descending
+ by creation, modification, or last opened dates). Internally, the endpoint
+ aggregates results from each space, merges and sorts them (after last modified
+ date by default), and returns a unified, paginated list of objects that match
+ the search parameters.
parameters:
- description: The number of items to skip before starting to collect the result
set
@@ -764,6 +786,10 @@ paths:
- search
/spaces:
get:
+ description: Retrieves a paginated list of all spaces that are accessible by
+ the authenticated user. Each space record contains detailed information such
+ as the space ID, name, icon (derived either from an emoji or image URL), and
+ additional metadata. This endpoint is key to displaying a user’s workspaces.
parameters:
- description: The number of items to skip before starting to collect the result
set
@@ -804,6 +830,12 @@ paths:
tags:
- spaces
post:
+ description: Creates a new workspace (or space) based on a supplied name in
+ the JSON request body. The endpoint is subject to rate limiting and automatically
+ applies default configurations such as generating a random icon and initializing
+ the workspace with default settings (for example, a default dashboard or home
+ page). On success, the new space’s full metadata is returned, enabling the
+ client to immediately switch context to the new space.
requestBody:
content:
application/json:
@@ -849,6 +881,10 @@ paths:
- spaces
/spaces/{space_id}:
get:
+ description: Fetches full details about a single space identified by its space
+ ID. The response includes metadata such as the space name, icon, and various
+ workspace IDs (home, archive, profile, etc.). This detailed view supports
+ use cases such as displaying space-specific settings.
parameters:
- description: Space ID
in: path
@@ -888,6 +924,11 @@ paths:
- spaces
/spaces/{space_id}/members:
get:
+ description: Returns a paginated list of members belonging to the specified
+ space. Each member record includes the member’s profile ID, name, icon (which
+ may be derived from an emoji or image), network identity, global name, and
+ role (e.g. Reader, Writer, Owner). This endpoint supports collaborative features
+ by allowing clients to show who is in a space and manage access rights.
parameters:
- description: Space ID
in: path
@@ -935,6 +976,10 @@ paths:
- spaces
/spaces/{space_id}/members/{member_id}:
get:
+ description: Fetches detailed information about a single member within a space.
+ The endpoint returns the member’s identifier, name, icon, identity, global
+ name, and role. This is useful for user profile pages, permission management,
+ and displaying member-specific information in collaborative environments.
parameters:
- description: Space ID
in: path
@@ -980,6 +1025,12 @@ paths:
- spaces
/spaces/{space_id}/objects:
get:
+ description: Retrieves a paginated list of objects in the given space. The endpoint
+ takes query parameters for pagination (offset and limit) and returns detailed
+ data about each object including its ID, name, icon, type information, a snippet
+ of the content (if applicable), layout, space ID, blocks and details. It is
+ intended for building views where users can see all objects in a space at
+ a glance.
parameters:
- description: Space ID
in: path
@@ -1026,6 +1077,14 @@ paths:
tags:
- objects
post:
+ description: Creates a new object in the specified space using a JSON payload.
+ The creation process is subject to rate limiting. The payload must include
+ key details such as the object name, icon, description, body content (which
+ may support Markdown), source URL (required for bookmark objects), template
+ identifier, and the unique key for the object type. Post-creation, additional
+ operations (like setting featured relations or fetching bookmark metadata)
+ may occur. The endpoint then returns the full object data, ready for further
+ interactions.
parameters:
- description: Space ID
in: path
@@ -1078,6 +1137,11 @@ paths:
- objects
/spaces/{space_id}/objects/{object_id}:
delete:
+ description: This endpoint “deletes” an object by marking it as archived. The
+ deletion process is performed safely and is subject to rate limiting. It returns
+ the object’s details after it has been archived. Proper error handling is
+ in place for situations such as when the object isn’t found or the deletion
+ cannot be performed because of permission issues.
parameters:
- description: Space ID
in: path
@@ -1134,6 +1198,12 @@ paths:
tags:
- objects
get:
+ description: Fetches the full details of a single object identified by the object
+ ID within the specified space. The response includes not only basic metadata
+ (ID, name, icon, type) but also the complete set of blocks (which may include
+ text, files, and relations) and extra details (such as timestamps and linked
+ member information). This endpoint is essential when a client needs to render
+ or edit the full object view.
parameters:
- description: Space ID
in: path
@@ -1179,6 +1249,13 @@ paths:
- objects
/spaces/{space_id}/objects/{object_id}/export/{format}:
post:
+ description: This endpoint exports a single object from the specified space
+ into a desired format. The export format is provided as a path parameter (currently
+ supporting “markdown” and “protobuf”), and clients can optionally specify
+ an export path in the request body. The endpoint calls an export service which
+ converts the object’s content into the requested format and returns the file
+ path where the exported data is stored. It is useful for data backup, sharing,
+ or further processing.
parameters:
- description: Space ID
in: path
@@ -1238,6 +1315,12 @@ paths:
- export
/spaces/{space_id}/search:
post:
+ description: This endpoint performs a focused search within a single space (specified
+ by the space_id path parameter). Like the global search, it accepts pagination
+ parameters and a JSON payload containing the search query, object types, and
+ sorting preferences. The search is limited to the provided space and returns
+ a list of objects that match the query. This allows clients to implement space‑specific
+ filtering without having to process extraneous results.
parameters:
- description: Space ID
in: path
@@ -1292,6 +1375,11 @@ paths:
- search
/spaces/{space_id}/types:
get:
+ description: This endpoint retrieves a paginated list of object types (e.g.
+ 'Page', 'Note', 'Task') available within the specified space. Each type’s
+ record includes its unique identifier, unique key, display name, icon, and
+ a recommended layout. Clients use this information when offering choices for
+ object creation or for filtering objects by type.
parameters:
- description: Space ID
in: path
@@ -1339,6 +1427,11 @@ paths:
- types
/spaces/{space_id}/types/{type_id}:
get:
+ description: Fetches detailed information about one specific object type by
+ its ID. This includes the type’s unique key, name, icon, and recommended layout.
+ This detailed view assists clients in understanding the expected structure
+ and style for objects of that type and in guiding the user interface (such
+ as displaying appropriate icons or layout hints).
parameters:
- description: Space ID
in: path
@@ -1384,6 +1477,11 @@ paths:
- types
/spaces/{space_id}/types/{type_id}/templates:
get:
+ description: This endpoint returns a paginated list of templates that are associated
+ with a specific object type within a space. Templates provide pre‑configured
+ structures for creating new objects. Each template record contains its identifier,
+ name, and icon, so that clients can offer users a selection of templates when
+ creating objects.
parameters:
- description: Space ID
in: path
@@ -1437,6 +1535,10 @@ paths:
- types
/spaces/{space_id}/types/{type_id}/templates/{template_id}:
get:
+ description: Fetches full details for one template associated with a particular
+ object type in a space. The response provides the template’s identifier, name,
+ icon, and any other relevant metadata. This endpoint is useful when a client
+ needs to preview or apply a template to prefill object creation fields.
parameters:
- description: Space ID
in: path
@@ -1488,6 +1590,10 @@ paths:
- types
/v1/spaces/{space_id}/lists/{list_id}/objects:
get:
+ description: Returns a paginated list of objects that are associated with a
+ specific list (or collection) within a space. This endpoint helps clients
+ to manage grouped objects (for example, tasks within a list) by returning
+ detailed object information for each item of the list.
parameters:
- description: Space ID
in: path
@@ -1544,6 +1650,10 @@ paths:
tags:
- lists
post:
+ description: Enables clients to add one or more objects to a specific list by
+ submitting a JSON array of object IDs. Upon success, the endpoint returns
+ a confirmation message. This endpoint is vital for building user interfaces
+ that allow drag‑and‑drop or multi‑select additions to collections.
parameters:
- description: Space ID
in: path
@@ -1604,6 +1714,11 @@ paths:
- lists
/v1/spaces/{space_id}/lists/{list_id}/objects/{object_id}:
delete:
+ description: Removes a given object from the specified list in a space. The
+ endpoint takes the space, list, and object identifiers as path parameters.
+ It's subject to rate limiting and returns a success message on completion.
+ It is used for dynamically managing collections without affecting the underlying
+ object data.
parameters:
- description: Space ID
in: path
diff --git a/core/api/internal/auth/handler.go b/core/api/internal/auth/handler.go
index 21900c9946..46cdbb1887 100644
--- a/core/api/internal/auth/handler.go
+++ b/core/api/internal/auth/handler.go
@@ -10,15 +10,16 @@ import (
// DisplayCodeHandler starts a new challenge and returns the challenge ID
//
-// @Summary Start new challenge
-// @Tags auth
-// @Accept json
-// @Produce json
-// @Param app_name query string true "App name requesting the challenge"
-// @Success 200 {object} DisplayCodeResponse "Challenge ID"
-// @Failure 400 {object} util.ValidationError "Invalid input"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Router /auth/display_code [post]
+// @Summary Start new challenge
+// @Description This endpoint initiates a secure authentication flow by generating a new challenge. Clients must supply the name of the application (via a query parameter) that is requesting authentication. On success, the service returns a unique challenge ID. This challenge ID must then be used with the token endpoint (see below) to solve the challenge and retrieve an authentication token. In essence, this endpoint “boots up” the login process and is the first step in a multi-phase authentication sequence.
+// @Tags auth
+// @Accept json
+// @Produce json
+// @Param app_name query string true "App name requesting the challenge"
+// @Success 200 {object} DisplayCodeResponse "Challenge ID"
+// @Failure 400 {object} util.ValidationError "Invalid input"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /auth/display_code [post]
func DisplayCodeHandler(s *AuthService) gin.HandlerFunc {
return func(c *gin.Context) {
appName := c.Query("app_name")
@@ -40,16 +41,17 @@ func DisplayCodeHandler(s *AuthService) gin.HandlerFunc {
// TokenHandler retrieves an authentication token using a code and challenge ID
//
-// @Summary Retrieve token
-// @Tags auth
-// @Accept json
-// @Produce json
-// @Param challenge_id query string true "Challenge ID"
-// @Param code query string true "4-digit code retrieved from Anytype Desktop app"
-// @Success 200 {object} TokenResponse "Authentication token"
-// @Failure 400 {object} util.ValidationError "Invalid input"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Router /auth/token [post]
+// @Summary Retrieve token
+// @Description After receiving a challenge ID from the display_code endpoint, the client calls this endpoint to provide the corresponding 4-digit code (also via a query parameter) along with the challenge ID. The endpoint verifies that the challenge solution is correct and, if it is, returns an ephemeral session token together with a permanent app key. These tokens are then used in subsequent API requests to authorize access. This endpoint is central to ensuring that only properly authenticated sessions can access further resources.
+// @Tags auth
+// @Accept json
+// @Produce json
+// @Param challenge_id query string true "Challenge ID"
+// @Param code query string true "4-digit code retrieved from Anytype Desktop app"
+// @Success 200 {object} TokenResponse "Authentication token"
+// @Failure 400 {object} util.ValidationError "Invalid input"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /auth/token [post]
func TokenHandler(s *AuthService) gin.HandlerFunc {
return func(c *gin.Context) {
challengeId := c.Query("challenge_id")
diff --git a/core/api/internal/export/handler.go b/core/api/internal/export/handler.go
index b0a2813a42..cc4c058134 100644
--- a/core/api/internal/export/handler.go
+++ b/core/api/internal/export/handler.go
@@ -10,19 +10,20 @@ import (
// GetObjectExportHandler exports an object in specified format
//
-// @Summary Export object
-// @Tags export
-// @Accept json
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param object_id path string true "Object ID"
-// @Param format path string true "Export format" Enums(markdown,protobuf)
-// @Success 200 {object} ObjectExportResponse "Object exported successfully"
-// @Failure 400 {object} util.ValidationError "Bad request"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/objects/{object_id}/export/{format} [post]
+// @Summary Export object
+// @Description This endpoint exports a single object from the specified space into a desired format. The export format is provided as a path parameter (currently supporting “markdown” and “protobuf”), and clients can optionally specify an export path in the request body. The endpoint calls an export service which converts the object’s content into the requested format and returns the file path where the exported data is stored. It is useful for data backup, sharing, or further processing.
+// @Tags export
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param object_id path string true "Object ID"
+// @Param format path string true "Export format" Enums(markdown,protobuf)
+// @Success 200 {object} ObjectExportResponse "Object exported successfully"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/objects/{object_id}/export/{format} [post]
func GetObjectExportHandler(s *ExportService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
diff --git a/core/api/internal/list/handler.go b/core/api/internal/list/handler.go
index c5c6871ae5..761795a117 100644
--- a/core/api/internal/list/handler.go
+++ b/core/api/internal/list/handler.go
@@ -11,19 +11,20 @@ import (
// GetObjectsInListHandler
//
-// @Summary Get objects in list
-// @Tags lists
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param list_id path string true "List ID"
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return"
-// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [get]
+// @Summary Get objects in list
+// @Description Returns a paginated list of objects that are associated with a specific list (or collection) within a space. This endpoint helps clients to manage grouped objects (for example, tasks within a list) by returning detailed object information for each item of the list.
+// @Tags lists
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param list_id path string true "List ID"
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return"
+// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [get]
func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -48,20 +49,21 @@ func GetObjectsInListHandler(s *ListService) gin.HandlerFunc {
// AddObjectsToListHandler
//
-// @Summary Add objects to list
-// @Tags lists
-// @Accept json
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param list_id path string true "List ID"
-// @Param objects body []string true "List of object IDs"
-// @Success 200 {object} string "Objects added successfully"
-// @Failure 400 {object} util.ValidationError "Bad request"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [post]
+// @Summary Add objects to list
+// @Description Enables clients to add one or more objects to a specific list by submitting a JSON array of object IDs. Upon success, the endpoint returns a confirmation message. This endpoint is vital for building user interfaces that allow drag‑and‑drop or multi‑select additions to collections.
+// @Tags lists
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param list_id path string true "List ID"
+// @Param objects body []string true "List of object IDs"
+// @Success 200 {object} string "Objects added successfully"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects [post]
func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -91,19 +93,20 @@ func AddObjectsToListHandler(s *ListService) gin.HandlerFunc {
// RemoveObjectFromListHandler
//
-// @Summary Remove object from list
-// @Tags lists
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param list_id path string true "List ID"
-// @Param object_id path string true "Object ID"
-// @Success 200 {object} string "Objects removed successfully"
-// @Failure 400 {object} util.ValidationError "Bad request"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /v1/spaces/{space_id}/lists/{list_id}/objects/{object_id} [delete]
+// @Summary Remove object from list
+// @Description Removes a given object from the specified list in a space. The endpoint takes the space, list, and object identifiers as path parameters. It's subject to rate limiting and returns a success message on completion. It is used for dynamically managing collections without affecting the underlying object data.
+// @Tags lists
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param list_id path string true "List ID"
+// @Param object_id path string true "Object ID"
+// @Success 200 {object} string "Objects removed successfully"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /v1/spaces/{space_id}/lists/{list_id}/objects/{object_id} [delete]
func RemoveObjectFromListHandler(s *ListService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
diff --git a/core/api/internal/object/handler.go b/core/api/internal/object/handler.go
index a8a0aa25d1..c62f18768e 100644
--- a/core/api/internal/object/handler.go
+++ b/core/api/internal/object/handler.go
@@ -11,17 +11,18 @@ import (
// GetObjectsHandler retrieves a list of objects in a space
//
-// @Summary List objects
-// @Tags objects
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return" default(100) maximum(1000)
-// @Success 200 {object} pagination.PaginatedResponse[Object] "List of objects"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/objects [get]
+// @Summary List objects
+// @Description Retrieves a paginated list of objects in the given space. The endpoint takes query parameters for pagination (offset and limit) and returns detailed data about each object including its ID, name, icon, type information, a snippet of the content (if applicable), layout, space ID, blocks and details. It is intended for building views where users can see all objects in a space at a glance.
+// @Tags objects
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return" default(100) maximum(1000)
+// @Success 200 {object} pagination.PaginatedResponse[Object] "List of objects"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/objects [get]
func GetObjectsHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -47,17 +48,18 @@ func GetObjectsHandler(s *ObjectService) gin.HandlerFunc {
// GetObjectHandler retrieves an object in a space
//
-// @Summary Get object
-// @Tags objects
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param object_id path string true "Object ID"
-// @Success 200 {object} ObjectResponse "The requested object"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Resource not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/objects/{object_id} [get]
+// @Summary Get object
+// @Description Fetches the full details of a single object identified by the object ID within the specified space. The response includes not only basic metadata (ID, name, icon, type) but also the complete set of blocks (which may include text, files, and relations) and extra details (such as timestamps and linked member information). This endpoint is essential when a client needs to render or edit the full object view.
+// @Tags objects
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param object_id path string true "Object ID"
+// @Success 200 {object} ObjectResponse "The requested object"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Resource not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/objects/{object_id} [get]
func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -81,19 +83,20 @@ func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
// DeleteObjectHandler deletes an object in a space
//
-// @Summary Delete object
-// @Tags objects
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param object_id path string true "Object ID"
-// @Success 200 {object} ObjectResponse "The deleted object"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 403 {object} util.ForbiddenError "Forbidden"
-// @Failure 404 {object} util.NotFoundError "Resource not found"
-// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/objects/{object_id} [delete]
+// @Summary Delete object
+// @Description This endpoint “deletes” an object by marking it as archived. The deletion process is performed safely and is subject to rate limiting. It returns the object’s details after it has been archived. Proper error handling is in place for situations such as when the object isn’t found or the deletion cannot be performed because of permission issues.
+// @Tags objects
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param object_id path string true "Object ID"
+// @Success 200 {object} ObjectResponse "The deleted object"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 403 {object} util.ForbiddenError "Forbidden"
+// @Failure 404 {object} util.NotFoundError "Resource not found"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/objects/{object_id} [delete]
func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -118,19 +121,20 @@ func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
// CreateObjectHandler creates a new object in a space
//
-// @Summary Create object
-// @Tags objects
-// @Accept json
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param object body CreateObjectRequest true "Object to create"
-// @Success 200 {object} ObjectResponse "The created object"
-// @Failure 400 {object} util.ValidationError "Bad request"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/objects [post]
+// @Summary Create object
+// @Description Creates a new object in the specified space using a JSON payload. The creation process is subject to rate limiting. The payload must include key details such as the object name, icon, description, body content (which may support Markdown), source URL (required for bookmark objects), template identifier, and the unique key for the object type. Post-creation, additional operations (like setting featured relations or fetching bookmark metadata) may occur. The endpoint then returns the full object data, ready for further interactions.
+// @Tags objects
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param object body CreateObjectRequest true "Object to create"
+// @Success 200 {object} ObjectResponse "The created object"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/objects [post]
func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -164,17 +168,18 @@ func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
// GetTypesHandler retrieves a list of types in a space
//
-// @Summary List types
-// @Tags types
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return" default(100) maximum(1000)
-// @Success 200 {object} pagination.PaginatedResponse[Type] "List of types"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/types [get]
+// @Summary List types
+// @Description This endpoint retrieves a paginated list of object types (e.g. 'Page', 'Note', 'Task') available within the specified space. Each type’s record includes its unique identifier, unique key, display name, icon, and a recommended layout. Clients use this information when offering choices for object creation or for filtering objects by type.
+// @Tags types
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return" default(100) maximum(1000)
+// @Success 200 {object} pagination.PaginatedResponse[Type] "List of types"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/types [get]
func GetTypesHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -198,17 +203,18 @@ func GetTypesHandler(s *ObjectService) gin.HandlerFunc {
// GetTypeHandler retrieves a type in a space
//
-// @Summary Get type
-// @Tags types
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param type_id path string true "Type ID"
-// @Success 200 {object} TypeResponse "The requested type"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Resource not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/types/{type_id} [get]
+// @Summary Get type
+// @Description Fetches detailed information about one specific object type by its ID. This includes the type’s unique key, name, icon, and recommended layout. This detailed view assists clients in understanding the expected structure and style for objects of that type and in guiding the user interface (such as displaying appropriate icons or layout hints).
+// @Tags types
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param type_id path string true "Type ID"
+// @Success 200 {object} TypeResponse "The requested type"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Resource not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/types/{type_id} [get]
func GetTypeHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -232,18 +238,19 @@ func GetTypeHandler(s *ObjectService) gin.HandlerFunc {
// GetTemplatesHandler retrieves a list of templates for a type in a space
//
-// @Summary List templates
-// @Tags types
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param type_id path string true "Type ID"
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return" default(100) maximum(1000)
-// @Success 200 {object} pagination.PaginatedResponse[Template] "List of templates"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/types/{type_id}/templates [get]
+// @Summary List templates
+// @Description This endpoint returns a paginated list of templates that are associated with a specific object type within a space. Templates provide pre‑configured structures for creating new objects. Each template record contains its identifier, name, and icon, so that clients can offer users a selection of templates when creating objects.
+// @Tags types
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param type_id path string true "Type ID"
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return" default(100) maximum(1000)
+// @Success 200 {object} pagination.PaginatedResponse[Template] "List of templates"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/types/{type_id}/templates [get]
func GetTemplatesHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -271,18 +278,19 @@ func GetTemplatesHandler(s *ObjectService) gin.HandlerFunc {
// GetTemplateHandler retrieves a template for a type in a space
//
-// @Summary Get template
-// @Tags types
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param type_id path string true "Type ID"
-// @Param template_id path string true "Template ID"
-// @Success 200 {object} TemplateResponse "The requested template"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Resource not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/types/{type_id}/templates/{template_id} [get]
+// @Summary Get template
+// @Description Fetches full details for one template associated with a particular object type in a space. The response provides the template’s identifier, name, icon, and any other relevant metadata. This endpoint is useful when a client needs to preview or apply a template to prefill object creation fields.
+// @Tags types
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param type_id path string true "Type ID"
+// @Param template_id path string true "Template ID"
+// @Success 200 {object} TemplateResponse "The requested template"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Resource not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/types/{type_id}/templates/{template_id} [get]
func GetTemplateHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
diff --git a/core/api/internal/search/handler.go b/core/api/internal/search/handler.go
index 57bbe33182..9113b30e2a 100644
--- a/core/api/internal/search/handler.go
+++ b/core/api/internal/search/handler.go
@@ -11,18 +11,19 @@ import (
// GlobalSearchHandler searches and retrieves objects across all spaces
//
-// @Summary Search objects across all spaces
-// @Tags search
-// @Accept json
-// @Produce json
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return" default(100) maximum(1000)
-// @Param request body SearchRequest true "Search parameters"
-// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /search [post]
+// @Summary Search objects across all spaces
+// @Description This endpoint executes a global search over every space the user has access to. It accepts pagination parameters (offset and limit) and a JSON body containing search criteria. The criteria include a search query string, an optional list of object types, and sort options (e.g. ascending/descending by creation, modification, or last opened dates). Internally, the endpoint aggregates results from each space, merges and sorts them (after last modified date by default), and returns a unified, paginated list of objects that match the search parameters.
+// @Tags search
+// @Accept json
+// @Produce json
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return" default(100) maximum(1000)
+// @Param request body SearchRequest true "Search parameters"
+// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /search [post]
func GlobalSearchHandler(s *SearchService) gin.HandlerFunc {
return func(c *gin.Context) {
offset := c.GetInt("offset")
@@ -52,19 +53,20 @@ func GlobalSearchHandler(s *SearchService) gin.HandlerFunc {
// SearchHandler searches and retrieves objects within a space
//
-// @Summary Search objects within a space
-// @Tags search
-// @Accept json
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return" default(100) maximum(1000)
-// @Param request body SearchRequest true "Search parameters"
-// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/search [post]
+// @Summary Search objects within a space
+// @Description This endpoint performs a focused search within a single space (specified by the space_id path parameter). Like the global search, it accepts pagination parameters and a JSON payload containing the search query, object types, and sorting preferences. The search is limited to the provided space and returns a list of objects that match the query. This allows clients to implement space‑specific filtering without having to process extraneous results.
+// @Tags search
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return" default(100) maximum(1000)
+// @Param request body SearchRequest true "Search parameters"
+// @Success 200 {object} pagination.PaginatedResponse[object.Object] "List of objects"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/search [post]
func SearchHandler(s *SearchService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceID := c.Param("space_id")
diff --git a/core/api/internal/space/handler.go b/core/api/internal/space/handler.go
index 8c67c671b5..e52dcb2f62 100644
--- a/core/api/internal/space/handler.go
+++ b/core/api/internal/space/handler.go
@@ -11,16 +11,17 @@ import (
// GetSpacesHandler retrieves a list of spaces
//
-// @Summary List spaces
-// @Tags spaces
-// @Produce json
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return" default(100) maximum(1000)
-// @Success 200 {object} pagination.PaginatedResponse[Space] "List of spaces"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces [get]
+// @Summary List spaces
+// @Description Retrieves a paginated list of all spaces that are accessible by the authenticated user. Each space record contains detailed information such as the space ID, name, icon (derived either from an emoji or image URL), and additional metadata. This endpoint is key to displaying a user’s workspaces.
+// @Tags spaces
+// @Produce json
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return" default(100) maximum(1000)
+// @Success 200 {object} pagination.PaginatedResponse[Space] "List of spaces"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces [get]
func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
offset := c.GetInt("offset")
@@ -44,16 +45,17 @@ func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
// GetSpaceHandler retrieves a space
//
-// @Summary Get space
-// @Tags spaces
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Success 200 {object} SpaceResponse "Space"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Space not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id} [get]
+// @Summary Get space
+// @Description Fetches full details about a single space identified by its space ID. The response includes metadata such as the space name, icon, and various workspace IDs (home, archive, profile, etc.). This detailed view supports use cases such as displaying space-specific settings.
+// @Tags spaces
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Success 200 {object} SpaceResponse "Space"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Space not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id} [get]
func GetSpaceHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -76,18 +78,19 @@ func GetSpaceHandler(s *SpaceService) gin.HandlerFunc {
// CreateSpaceHandler creates a new space
//
-// @Summary Create space
-// @Tags spaces
-// @Accept json
-// @Produce json
-// @Param name body CreateSpaceRequest true "Space to create"
-// @Success 200 {object} SpaceResponse "Space created successfully"
-// @Failure 400 {object} util.ValidationError "Bad request"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces [post]
+// @Summary Create space
+// @Description Creates a new workspace (or space) based on a supplied name in the JSON request body. The endpoint is subject to rate limiting and automatically applies default configurations such as generating a random icon and initializing the workspace with default settings (for example, a default dashboard or home page). On success, the new space’s full metadata is returned, enabling the client to immediately switch context to the new space.
+// @Tags spaces
+// @Accept json
+// @Produce json
+// @Param name body CreateSpaceRequest true "Space to create"
+// @Success 200 {object} SpaceResponse "Space created successfully"
+// @Failure 400 {object} util.ValidationError "Bad request"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces [post]
func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
nameRequest := CreateSpaceRequest{}
@@ -114,17 +117,18 @@ func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
// GetMembersHandler retrieves a list of members in a space
//
-// @Summary List members
-// @Tags spaces
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
-// @Param limit query int false "The number of items to return" default(100) maximum(1000)
-// @Success 200 {object} pagination.PaginatedResponse[Member] "List of members"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/members [get]
+// @Summary List members
+// @Description Returns a paginated list of members belonging to the specified space. Each member record includes the member’s profile ID, name, icon (which may be derived from an emoji or image), network identity, global name, and role (e.g. Reader, Writer, Owner). This endpoint supports collaborative features by allowing clients to show who is in a space and manage access rights.
+// @Tags spaces
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param offset query int false "The number of items to skip before starting to collect the result set" default(0)
+// @Param limit query int false "The number of items to return" default(100) maximum(1000)
+// @Success 200 {object} pagination.PaginatedResponse[Member] "List of members"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/members [get]
func GetMembersHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
@@ -148,17 +152,18 @@ func GetMembersHandler(s *SpaceService) gin.HandlerFunc {
// GetMemberHandler retrieves a member in a space
//
-// @Summary Get member
-// @Tags spaces
-// @Produce json
-// @Param space_id path string true "Space ID"
-// @Param member_id path string true "Member ID"
-// @Success 200 {object} MemberResponse "Member"
-// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
-// @Failure 404 {object} util.NotFoundError "Member not found"
-// @Failure 500 {object} util.ServerError "Internal server error"
-// @Security bearerauth
-// @Router /spaces/{space_id}/members/{member_id} [get]
+// @Summary Get member
+// @Description Fetches detailed information about a single member within a space. The endpoint returns the member’s identifier, name, icon, identity, global name, and role. This is useful for user profile pages, permission management, and displaying member-specific information in collaborative environments.
+// @Tags spaces
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param member_id path string true "Member ID"
+// @Success 200 {object} MemberResponse "Member"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Member not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Security bearerauth
+// @Router /spaces/{space_id}/members/{member_id} [get]
func GetMemberHandler(s *SpaceService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
From 8935a5bb112724806115a94ca811e9adfaaa9e79 Mon Sep 17 00:00:00 2001
From: Jannis Metrikat <120120832+jmetrikat@users.noreply.github.com>
Date: Fri, 21 Feb 2025 13:34:06 +0100
Subject: [PATCH 31/31] GO-4459: Set metadata header with API version
---
core/api/server/middleware.go | 8 ++++++++
core/api/server/router.go | 1 +
2 files changed, 9 insertions(+)
diff --git a/core/api/server/middleware.go b/core/api/server/middleware.go
index 1313127f80..2317c935f0 100644
--- a/core/api/server/middleware.go
+++ b/core/api/server/middleware.go
@@ -95,3 +95,11 @@ func (s *Server) ensureAccountInfo(accountService account.Service) gin.HandlerFu
c.Next()
}
}
+
+// ensureMetadataHeader is a middleware that ensures the metadata header is set.
+func (s *Server) ensureMetadataHeader() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ c.Writer.Header().Set("X-API-Version", "0.0.2")
+ c.Next()
+ }
+}
diff --git a/core/api/server/router.go b/core/api/server/router.go
index f3397da1c0..67237092c8 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -37,6 +37,7 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
router := gin.New()
router.Use(gin.Recovery())
+ router.Use(s.ensureMetadataHeader())
if debug {
router.Use(gin.Logger())