From dd0764eb600f7c47e6ace83eb94a347b58a4a58d Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 30 Oct 2024 14:08:03 +0000 Subject: [PATCH] Putting view mapping in place, updating openAPI spec. --- packages/server/specs/openapi.json | 423 +++++++++++++++++- packages/server/specs/openapi.yaml | 290 +++++++++++- packages/server/specs/resources/index.ts | 4 + .../api/controllers/public/mapping/index.ts | 2 + .../api/controllers/public/mapping/types.ts | 3 + .../api/controllers/public/mapping/views.ts | 26 ++ .../src/api/controllers/public/views.ts | 3 +- .../api/routes/public/middleware/mapper.ts | 30 +- packages/server/src/definitions/openapi.ts | 180 ++++++++ 9 files changed, 943 insertions(+), 18 deletions(-) create mode 100644 packages/server/src/api/controllers/public/mapping/views.ts diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index f3091a1fc7..c80f947fad 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -423,6 +423,62 @@ }, "metrics": { "value": "# HELP budibase_os_uptime Time in seconds that the host operating system has been up.\n# TYPE budibase_os_uptime counter\nbudibase_os_uptime 54958\n# HELP budibase_os_free_mem Bytes of memory free for usage on the host operating system.\n# TYPE budibase_os_free_mem gauge\nbudibase_os_free_mem 804507648\n# HELP budibase_os_total_mem Total bytes of memory on the host operating system.\n# TYPE budibase_os_total_mem gauge\nbudibase_os_total_mem 16742404096\n# HELP budibase_os_used_mem Total bytes of memory in use on the host operating system.\n# TYPE budibase_os_used_mem gauge\nbudibase_os_used_mem 15937896448\n# HELP budibase_os_load1 Host operating system load average.\n# TYPE budibase_os_load1 gauge\nbudibase_os_load1 1.91\n# HELP budibase_os_load5 Host operating system load average.\n# TYPE budibase_os_load5 gauge\nbudibase_os_load5 1.75\n# HELP budibase_os_load15 Host operating system load average.\n# TYPE budibase_os_load15 gauge\nbudibase_os_load15 1.56\n# HELP budibase_tenant_user_count The number of users created.\n# TYPE budibase_tenant_user_count gauge\nbudibase_tenant_user_count 1\n# HELP budibase_tenant_app_count The number of apps created by a user.\n# TYPE budibase_tenant_app_count gauge\nbudibase_tenant_app_count 2\n# HELP budibase_tenant_production_app_count The number of apps a user has published.\n# TYPE budibase_tenant_production_app_count gauge\nbudibase_tenant_production_app_count 1\n# HELP budibase_tenant_dev_app_count The number of apps a user has unpublished in development.\n# TYPE budibase_tenant_dev_app_count gauge\nbudibase_tenant_dev_app_count 1\n# HELP budibase_tenant_db_count The number of couchdb databases including global tables such as _users.\n# TYPE budibase_tenant_db_count gauge\nbudibase_tenant_db_count 3\n# HELP budibase_quota_usage_apps The number of apps created.\n# TYPE budibase_quota_usage_apps gauge\nbudibase_quota_usage_apps 1\n# HELP budibase_quota_limit_apps The limit on the number of apps that can be created.\n# TYPE budibase_quota_limit_apps gauge\nbudibase_quota_limit_apps 9007199254740991\n# HELP budibase_quota_usage_rows The number of database rows used from the quota.\n# TYPE budibase_quota_usage_rows gauge\nbudibase_quota_usage_rows 0\n# HELP budibase_quota_limit_rows The limit on the number of rows that can be created.\n# TYPE budibase_quota_limit_rows gauge\nbudibase_quota_limit_rows 9007199254740991\n# HELP budibase_quota_usage_plugins The number of plugins in use.\n# TYPE budibase_quota_usage_plugins gauge\nbudibase_quota_usage_plugins 0\n# HELP budibase_quota_limit_plugins The limit on the number of plugins that can be created.\n# TYPE budibase_quota_limit_plugins gauge\nbudibase_quota_limit_plugins 9007199254740991\n# HELP budibase_quota_usage_user_groups The number of user groups created.\n# TYPE budibase_quota_usage_user_groups gauge\nbudibase_quota_usage_user_groups 0\n# HELP budibase_quota_limit_user_groups The limit on the number of user groups that can be created.\n# TYPE budibase_quota_limit_user_groups gauge\nbudibase_quota_limit_user_groups 9007199254740991\n# HELP budibase_quota_usage_queries The number of queries used in the current month.\n# TYPE budibase_quota_usage_queries gauge\nbudibase_quota_usage_queries 0\n# HELP budibase_quota_limit_queries The limit on the number of queries for the current month.\n# TYPE budibase_quota_limit_queries gauge\nbudibase_quota_limit_queries 9007199254740991\n# HELP budibase_quota_usage_automations The number of automations used in the current month.\n# TYPE budibase_quota_usage_automations gauge\nbudibase_quota_usage_automations 0\n# HELP budibase_quota_limit_automations The limit on the number of automations that can be created.\n# TYPE budibase_quota_limit_automations gauge\nbudibase_quota_limit_automations 9007199254740991\n" + }, + "view": { + "value": { + "data": { + "name": "peopleView", + "tableId": "ta_896a325f7e8147d2a2cda93c5d236511", + "schema": { + "name": { + "visible": true, + "readonly": false, + "order": 1, + "width": 300 + }, + "age": { + "visible": true, + "readonly": true, + "order": 2, + "width": 200 + }, + "salary": { + "visible": false, + "readonly": false + } + }, + "primaryDisplay": "name" + } + } + }, + "views": { + "value": { + "data": [ + { + "name": "peopleView", + "tableId": "ta_896a325f7e8147d2a2cda93c5d236511", + "schema": { + "name": { + "visible": true, + "readonly": false, + "order": 1, + "width": 300 + }, + "age": { + "visible": true, + "readonly": true, + "order": 2, + "width": 200 + }, + "salary": { + "visible": false, + "readonly": false + } + }, + "primaryDisplay": "name" + } + ] + } } }, "securitySchemes": { @@ -831,8 +887,7 @@ "type": "string", "enum": [ "static", - "dynamic", - "ai" + "dynamic" ], "description": "Defines whether this is a static or dynamic formula." } @@ -1042,8 +1097,7 @@ "type": "string", "enum": [ "static", - "dynamic", - "ai" + "dynamic" ], "description": "Defines whether this is a static or dynamic formula." } @@ -1264,8 +1318,7 @@ "type": "string", "enum": [ "static", - "dynamic", - "ai" + "dynamic" ], "description": "Defines whether this is a static or dynamic formula." } @@ -2024,6 +2077,161 @@ "required": [ "data" ] + }, + "view": { + "description": "The view to be created/updated.", + "type": "object", + "required": [ + "name", + "schema" + ], + "properties": { + "name": { + "description": "The name of the view.", + "type": "string" + }, + "primaryDisplay": { + "type": "string", + "description": "A column used to display rows from this view - usually used when rendered in tables." + }, + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + } + } + } + } + } + }, + "viewOutput": { + "type": "object", + "properties": { + "data": { + "description": "The view to be created/updated.", + "type": "object", + "required": [ + "name", + "schema", + "id" + ], + "properties": { + "name": { + "description": "The name of the view.", + "type": "string" + }, + "primaryDisplay": { + "type": "string", + "description": "A column used to display rows from this view - usually used when rendered in tables." + }, + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + } + } + } + }, + "id": { + "description": "The ID of the view.", + "type": "string" + } + } + } + }, + "required": [ + "data" + ] + }, + "viewSearch": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "description": "The view to be created/updated.", + "type": "object", + "required": [ + "name", + "schema", + "id" + ], + "properties": { + "name": { + "description": "The name of the view.", + "type": "string" + }, + "primaryDisplay": { + "type": "string", + "description": "A column used to display rows from this view - usually used when rendered in tables." + }, + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + } + } + } + }, + "id": { + "description": "The ID of the view.", + "type": "string" + } + } + } + } + }, + "required": [ + "data" + ] } } }, @@ -3115,6 +3323,209 @@ } } } + }, + "/views": { + "post": { + "operationId": "viewCreate", + "summary": "Create a view", + "description": "Create a view, this can be against an internal or external table.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/appId" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/view" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + }, + "responses": { + "200": { + "description": "Returns the created view, including the ID which has been generated for it.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + } + }, + "/views/{viewId}": { + "put": { + "operationId": "viewUpdate", + "summary": "Update a view", + "description": "Update a view, this can be against an internal or external table.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/viewId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/view" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + }, + "responses": { + "200": { + "description": "Returns the updated view.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + }, + "delete": { + "operationId": "viewDestroy", + "summary": "Delete a view", + "description": "Delete a view, this can be against an internal or external table.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/viewId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "responses": { + "200": { + "description": "Returns the deleted view.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + }, + "get": { + "operationId": "viewGetById", + "summary": "Retrieve a view", + "description": "Lookup a view, this could be internal or external.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/viewId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "responses": { + "200": { + "description": "Returns the retrieved view.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + } + }, + "/views/search": { + "post": { + "operationId": "viewSearch", + "summary": "Search for views", + "description": "Based on view properties (currently only name) search for views.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/appId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewSearch" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the found views, based on the search parameters.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewSearch" + }, + "examples": { + "views": { + "$ref": "#/components/examples/views" + } + } + } + } + } + } + } } }, "tags": [] diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 1e9b9921cf..9a2ce6e0da 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -442,6 +442,46 @@ components: # TYPE budibase_quota_limit_automations gauge budibase_quota_limit_automations 9007199254740991 + view: + value: + data: + name: peopleView + tableId: ta_896a325f7e8147d2a2cda93c5d236511 + schema: + name: + visible: true + readonly: false + order: 1 + width: 300 + age: + visible: true + readonly: true + order: 2 + width: 200 + salary: + visible: false + readonly: false + primaryDisplay: name + views: + value: + data: + - name: peopleView + tableId: ta_896a325f7e8147d2a2cda93c5d236511 + schema: + name: + visible: true + readonly: false + order: 1 + width: 300 + age: + visible: true + readonly: true + order: 2 + width: 200 + salary: + visible: false + readonly: false + primaryDisplay: name securitySchemes: ApiKeyAuth: type: apiKey @@ -761,7 +801,6 @@ components: enum: - static - dynamic - - ai description: Defines whether this is a static or dynamic formula. - type: object properties: @@ -931,7 +970,6 @@ components: enum: - static - dynamic - - ai description: Defines whether this is a static or dynamic formula. - type: object properties: @@ -1108,7 +1146,6 @@ components: enum: - static - dynamic - - ai description: Defines whether this is a static or dynamic formula. - type: object properties: @@ -1704,6 +1741,134 @@ components: - userIds required: - data + view: + description: The view to be created/updated. + type: object + required: + - name + - schema + properties: + name: + description: The name of the view. + type: string + primaryDisplay: + type: string + description: A column used to display rows from this view - usually used when + rendered in tables. + schema: + type: object + additionalProperties: + type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able to access + it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + viewOutput: + type: object + properties: + data: + description: The view to be created/updated. + type: object + required: + - name + - schema + - id + properties: + name: + description: The name of the view. + type: string + primaryDisplay: + type: string + description: A column used to display rows from this view - usually used when + rendered in tables. + schema: + type: object + additionalProperties: + type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able to + access it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + id: + description: The ID of the view. + type: string + required: + - data + viewSearch: + type: object + properties: + data: + type: array + items: + description: The view to be created/updated. + type: object + required: + - name + - schema + - id + properties: + name: + description: The name of the view. + type: string + primaryDisplay: + type: string + description: A column used to display rows from this view - usually used when + rendered in tables. + schema: + type: object + additionalProperties: + type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able to + access it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + id: + description: The ID of the view. + type: string + required: + - data security: - ApiKeyAuth: [] paths: @@ -2359,4 +2524,123 @@ paths: examples: users: $ref: "#/components/examples/users" + /views: + post: + operationId: viewCreate + summary: Create a view + description: Create a view, this can be against an internal or external table. + tags: + - views + parameters: + - $ref: "#/components/parameters/appId" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/view" + examples: + view: + $ref: "#/components/examples/view" + responses: + "200": + description: Returns the created view, including the ID which has been generated + for it. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + "/views/{viewId}": + put: + operationId: viewUpdate + summary: Update a view + description: Update a view, this can be against an internal or external table. + tags: + - views + parameters: + - $ref: "#/components/parameters/viewId" + - $ref: "#/components/parameters/appId" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/view" + examples: + view: + $ref: "#/components/examples/view" + responses: + "200": + description: Returns the updated view. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + delete: + operationId: viewDestroy + summary: Delete a view + description: Delete a view, this can be against an internal or external table. + tags: + - views + parameters: + - $ref: "#/components/parameters/viewId" + - $ref: "#/components/parameters/appId" + responses: + "200": + description: Returns the deleted view. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + get: + operationId: viewGetById + summary: Retrieve a view + description: Lookup a view, this could be internal or external. + tags: + - views + parameters: + - $ref: "#/components/parameters/viewId" + - $ref: "#/components/parameters/appId" + responses: + "200": + description: Returns the retrieved view. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + /views/search: + post: + operationId: viewSearch + summary: Search for views + description: Based on view properties (currently only name) search for views. + tags: + - views + parameters: + - $ref: "#/components/parameters/appId" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/viewSearch" + responses: + "200": + description: Returns the found views, based on the search parameters. + content: + application/json: + schema: + $ref: "#/components/schemas/viewSearch" + examples: + views: + $ref: "#/components/examples/views" tags: [] diff --git a/packages/server/specs/resources/index.ts b/packages/server/specs/resources/index.ts index c06148b7de..0d32f2a007 100644 --- a/packages/server/specs/resources/index.ts +++ b/packages/server/specs/resources/index.ts @@ -6,6 +6,7 @@ import user from "./user" import metrics from "./metrics" import misc from "./misc" import roles from "./roles" +import view from "./view" export const examples = { ...application.getExamples(), @@ -15,6 +16,8 @@ export const examples = { ...user.getExamples(), ...misc.getExamples(), ...metrics.getExamples(), + ...roles.getExamples(), + ...view.getExamples(), } export const schemas = { @@ -25,4 +28,5 @@ export const schemas = { ...user.getSchemas(), ...misc.getSchemas(), ...roles.getSchemas(), + ...view.getSchemas(), } diff --git a/packages/server/src/api/controllers/public/mapping/index.ts b/packages/server/src/api/controllers/public/mapping/index.ts index 0cdcfbbe4b..b765f4bd76 100644 --- a/packages/server/src/api/controllers/public/mapping/index.ts +++ b/packages/server/src/api/controllers/public/mapping/index.ts @@ -3,6 +3,7 @@ import applications from "./applications" import users from "./users" import rows from "./rows" import queries from "./queries" +import views from "./views" export default { ...tables, @@ -10,4 +11,5 @@ export default { ...users, ...rows, ...queries, + ...views, } diff --git a/packages/server/src/api/controllers/public/mapping/types.ts b/packages/server/src/api/controllers/public/mapping/types.ts index 9fea9b7213..6cbcfddb92 100644 --- a/packages/server/src/api/controllers/public/mapping/types.ts +++ b/packages/server/src/api/controllers/public/mapping/types.ts @@ -9,6 +9,9 @@ export type CreateApplicationParams = components["schemas"]["application"] export type Table = components["schemas"]["tableOutput"]["data"] export type CreateTableParams = components["schemas"]["table"] +export type View = components["schemas"]["viewOutput"]["data"] +export type CreateViewParams = components["schemas"]["view"] + export type Row = components["schemas"]["rowOutput"]["data"] export type RowSearch = components["schemas"]["searchOutput"] export type CreateRowParams = components["schemas"]["row"] diff --git a/packages/server/src/api/controllers/public/mapping/views.ts b/packages/server/src/api/controllers/public/mapping/views.ts new file mode 100644 index 0000000000..b6cf64542e --- /dev/null +++ b/packages/server/src/api/controllers/public/mapping/views.ts @@ -0,0 +1,26 @@ +import { View } from "./types" + +function view(body: any): View { + return { + id: body.id, + name: body.name, + schema: body.schema, + primaryDisplay: body.primaryDisplay, + } +} + +function mapView(ctx: any): { data: View } { + return { + data: view(ctx.body), + } +} + +function mapViews(ctx: any): { data: View[] } { + const tables = ctx.body.map((body: any) => view(body)) + return { data: tables } +} + +export default { + mapView, + mapViews, +} diff --git a/packages/server/src/api/controllers/public/views.ts b/packages/server/src/api/controllers/public/views.ts index 85979126ff..f3265aa70d 100644 --- a/packages/server/src/api/controllers/public/views.ts +++ b/packages/server/src/api/controllers/public/views.ts @@ -18,8 +18,7 @@ function fixView(view: ViewV2, params?: { viewId: string }) { export async function search(ctx: UserCtx, next: Next) { const { name } = ctx.request.body - // TODO: need a view search endpoint - // await controller.v2.fetch(ctx) + await controller.v2.fetch(ctx) ctx.body = stringSearch(ctx.body, name) await next() } diff --git a/packages/server/src/api/routes/public/middleware/mapper.ts b/packages/server/src/api/routes/public/middleware/mapper.ts index 03feb6cc5c..9d0cae5d61 100644 --- a/packages/server/src/api/routes/public/middleware/mapper.ts +++ b/packages/server/src/api/routes/public/middleware/mapper.ts @@ -1,9 +1,10 @@ import { Ctx } from "@budibase/types" import mapping from "../../../controllers/public/mapping" -enum Resources { +enum Resource { APPLICATION = "applications", TABLES = "tables", + VIEWS = "views", ROWS = "rows", USERS = "users", QUERIES = "queries", @@ -15,7 +16,7 @@ function isAttachment(ctx: Ctx) { } function isArrayResponse(ctx: Ctx) { - return ctx.url.endsWith(Resources.SEARCH) || Array.isArray(ctx.body) + return ctx.url.endsWith(Resource.SEARCH) || Array.isArray(ctx.body) } function noResponse(ctx: Ctx) { @@ -38,6 +39,14 @@ function processTables(ctx: Ctx) { } } +function processViews(ctx: Ctx) { + if (isArrayResponse(ctx)) { + return mapping.mapViews(ctx) + } else { + return mapping.mapView(ctx) + } +} + function processRows(ctx: Ctx) { if (isArrayResponse(ctx)) { return mapping.mapRowSearch(ctx) @@ -71,20 +80,27 @@ export default async (ctx: Ctx, next: any) => { let body = {} switch (urlParts[0]) { - case Resources.APPLICATION: + case Resource.APPLICATION: body = processApplications(ctx) break - case Resources.TABLES: - if (urlParts[2] === Resources.ROWS) { + case Resource.TABLES: + if (urlParts[2] === Resource.ROWS) { body = processRows(ctx) } else { body = processTables(ctx) } break - case Resources.USERS: + case Resource.VIEWS: + if (urlParts[2] === Resource.ROWS) { + body = processRows(ctx) + } else { + body = processViews(ctx) + } + break + case Resource.USERS: body = processUsers(ctx) break - case Resources.QUERIES: + case Resource.QUERIES: body = processQueries(ctx) break } diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index 4479c89d9d..9d68e11185 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -93,6 +93,22 @@ export interface paths { /** Based on user properties (currently only name) search for users. */ post: operations["userSearch"]; }; + "/views": { + /** Create a view, this can be against an internal or external table. */ + post: operations["viewCreate"]; + }; + "/views/{viewId}": { + /** Lookup a view, this could be internal or external. */ + get: operations["viewGetById"]; + /** Update a view, this can be against an internal or external table. */ + put: operations["viewUpdate"]; + /** Delete a view, this can be against an internal or external table. */ + delete: operations["viewDestroy"]; + }; + "/views/search": { + /** Based on view properties (currently only name) search for views. */ + post: operations["viewSearch"]; + }; } export interface components { @@ -813,6 +829,70 @@ export interface components { userIds: string[]; }; }; + /** @description The view to be created/updated. */ + view: { + /** @description The name of the view. */ + name: string; + /** @description A column used to display rows from this view - usually used when rendered in tables. */ + primaryDisplay?: string; + schema: { + [key: string]: { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + }; + }; + }; + viewOutput: { + /** @description The view to be created/updated. */ + data: { + /** @description The name of the view. */ + name: string; + /** @description A column used to display rows from this view - usually used when rendered in tables. */ + primaryDisplay?: string; + schema: { + [key: string]: { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + }; + }; + /** @description The ID of the view. */ + id: string; + }; + }; + viewSearch: { + data: { + /** @description The name of the view. */ + name: string; + /** @description A column used to display rows from this view - usually used when rendered in tables. */ + primaryDisplay?: string; + schema: { + [key: string]: { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + }; + }; + /** @description The ID of the view. */ + id: string; + }[]; + }; }; parameters: { /** @description The ID of the table which this request is targeting. */ @@ -1409,6 +1489,106 @@ export interface operations { }; }; }; + /** Create a view, this can be against an internal or external table. */ + viewCreate: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the created view, including the ID which has been generated for it. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["view"]; + }; + }; + }; + /** Lookup a view, this could be internal or external. */ + viewGetById: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the retrieved view. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + }; + /** Update a view, this can be against an internal or external table. */ + viewUpdate: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the updated view. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["view"]; + }; + }; + }; + /** Delete a view, this can be against an internal or external table. */ + viewDestroy: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the deleted view. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + }; + /** Based on view properties (currently only name) search for views. */ + viewSearch: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the found views, based on the search parameters. */ + 200: { + content: { + "application/json": components["schemas"]["viewSearch"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["viewSearch"]; + }; + }; + }; } export interface external {}