From e71dda53bf19fd195c0fe3d98e36751a04adf8e3 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 21 Feb 2022 16:37:02 +0000 Subject: [PATCH] Updating table schema and adding query endpoints. --- packages/server/specs/openapi.json | 280 ++++++++++++++---- packages/server/specs/openapi.yaml | 211 ++++++++++--- packages/server/specs/schemas.js | 125 +++++++- .../src/api/controllers/public/queries.js | 7 + .../server/src/api/routes/public/queries.js | 21 ++ .../server/src/api/routes/public/tables.js | 11 +- 6 files changed, 548 insertions(+), 107 deletions(-) create mode 100644 packages/server/src/api/controllers/public/queries.js diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index a52c524aec..beb1eaeb65 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -183,31 +183,187 @@ "description": "The name of the table", "type": "string" }, + "primaryDisplay": { + "type": "string", + "description": "The name of the column which should be used in relationship tags when relating to this table." + }, "schema": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "string", - "longform", - "options", - "number", - "boolean", - "array", - "datetime", - "attachment", - "link", - "formula", - "auto", - "json", - "internal" - ] + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "link" + ], + "description": "A relationship column." + }, + "constraints": { + "type": "object", + "description": "A constraint can be applied to the column which will be validated against when a row is saved.", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "object", + "boolean" + ] + }, + "presence": { + "type": "boolean", + "description": "Defines whether the column is required or not." + } + } + }, + "name": { + "type": "string", + "description": "The name of the column." + }, + "autocolumn": { + "type": "boolean", + "description": "Defines whether the column is automatically generated." + }, + "fieldName": { + "type": "string", + "description": "The name of the column which a relationship column is related to in another table." + }, + "tableId": { + "type": "string", + "description": "The ID of the table which a relationship column is related to." + }, + "relationshipType": { + "type": "string", + "enum": [ + "one-to-many", + "many-to-one", + "many-to-many" + ], + "description": "Defines the type of relationship that this column will be used for." + }, + "through": { + "type": "string", + "description": "When using a SQL table that contains many to many relationships this defines the table the relationships are linked through." + }, + "foreignKey": { + "type": "string", + "description": "When using a SQL table that contains a one to many relationship this defines the foreign key." + }, + "throughFrom": { + "type": "string", + "description": "When using a SQL table that utilises a through table, this defines the primary key in the through table for this table." + }, + "throughTo": { + "type": "string", + "description": "When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table." + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "formula" + ], + "description": "A formula column." + }, + "constraints": { + "type": "object", + "description": "A constraint can be applied to the column which will be validated against when a row is saved.", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "object", + "boolean" + ] + }, + "presence": { + "type": "boolean", + "description": "Defines whether the column is required or not." + } + } + }, + "name": { + "type": "string", + "description": "The name of the column." + }, + "autocolumn": { + "type": "boolean", + "description": "Defines whether the column is automatically generated." + }, + "formula": { + "type": "string", + "description": "Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format." + }, + "formulaType": { + "type": "string", + "enum": [ + "static", + "dynamic" + ], + "description": "Defines whether this is a static or dynamic formula." + } + } + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "longform", + "options", + "number", + "boolean", + "array", + "datetime", + "attachment", + "link", + "formula", + "auto", + "json", + "internal" + ], + "description": "Defines the type of the column, most explain themselves, a link column is a relationship." + }, + "constraints": { + "type": "object", + "description": "A constraint can be applied to the column which will be validated against when a row is saved.", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "object", + "boolean" + ] + }, + "presence": { + "type": "boolean", + "description": "Defines whether the column is required or not." + } + } + }, + "name": { + "type": "string", + "description": "The name of the column." + }, + "autocolumn": { + "type": "boolean", + "description": "Defines whether the column is automatically generated." + } } } - } + ] } } } @@ -219,6 +375,22 @@ } ], "paths": { + "/queries/search": { + "post": { + "summary": "Search for a query based on its name.", + "tags": [ + "queries" + ] + } + }, + "/queries/{queryId}": { + "post": { + "summary": "Execute a query and retrieve its response.", + "tags": [ + "queries" + ] + } + }, "/tables/{tableId}/rows/search": { "post": { "summary": "Used to search for rows within a table.", @@ -573,7 +745,7 @@ "properties": { "name": { "type": "string", - "description": "The name of the table, this should be an exact match (ignoring case)." + "description": "The name of the table, this is a case insensitive search using the provided name as a starts with search." } } } @@ -644,37 +816,6 @@ } } } - }, - "get": { - "summary": "Get all the tables, internal and external within an app.", - "tags": [ - "tables" - ], - "parameters": [ - { - "$ref": "#/components/parameters/tableId" - }, - { - "$ref": "#/components/parameters/appId" - } - ], - "responses": { - "200": { - "description": "Returns all of the tables which were found.", - "content": { - "application/json": { - "schema": { - "type": "object" - }, - "examples": { - "table": { - "$ref": "#/components/examples/row" - } - } - } - } - } - } } }, "/tables/:tableId": { @@ -725,6 +866,37 @@ } }, "/tables/{tableId}": { + "get": { + "summary": "Get a single table by its ID, internal and external within an app.", + "tags": [ + "tables" + ], + "parameters": [ + { + "$ref": "#/components/parameters/tableId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "responses": { + "200": { + "description": "Returns the table that was found.", + "content": { + "application/json": { + "schema": { + "type": "object" + }, + "examples": { + "table": { + "$ref": "#/components/examples/row" + } + } + } + } + } + } + }, "delete": { "summary": "Delete a single table and all of its data.", "tags": [ diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index d2cf091643..04b25647f1 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -123,30 +123,163 @@ components: name: description: The name of the table type: string + primaryDisplay: + type: string + description: The name of the column which should be used in relationship tags + when relating to this table. schema: - type: object - additionalProperties: - type: object - properties: - type: - type: string - enum: - - string - - longform - - options - - number - - boolean - - array - - datetime - - attachment - - link - - formula - - auto - - json - - internal + oneOf: + - type: object + properties: + type: + type: string + enum: + - link + description: A relationship column. + constraints: + type: object + description: A constraint can be applied to the column which will be validated + against when a row is saved. + properties: + type: + type: string + enum: + - string + - number + - object + - boolean + presence: + type: boolean + description: Defines whether the column is required or not. + name: + type: string + description: The name of the column. + autocolumn: + type: boolean + description: Defines whether the column is automatically generated. + fieldName: + type: string + description: The name of the column which a relationship column is related to in + another table. + tableId: + type: string + description: The ID of the table which a relationship column is related to. + relationshipType: + type: string + enum: + - one-to-many + - many-to-one + - many-to-many + description: Defines the type of relationship that this column will be used for. + through: + type: string + description: When using a SQL table that contains many to many relationships + this defines the table the relationships are linked through. + foreignKey: + type: string + description: When using a SQL table that contains a one to many relationship + this defines the foreign key. + throughFrom: + type: string + description: When using a SQL table that utilises a through table, this defines + the primary key in the through table for this table. + throughTo: + type: string + description: When using a SQL table that utilises a through table, this defines + the primary key in the through table for the related table. + - type: object + properties: + type: + type: string + enum: + - formula + description: A formula column. + constraints: + type: object + description: A constraint can be applied to the column which will be validated + against when a row is saved. + properties: + type: + type: string + enum: + - string + - number + - object + - boolean + presence: + type: boolean + description: Defines whether the column is required or not. + name: + type: string + description: The name of the column. + autocolumn: + type: boolean + description: Defines whether the column is automatically generated. + formula: + type: string + description: Defines a Handlebars or JavaScript formula to use, note that + Javascript formulas are expected to be provided in the + base64 format. + formulaType: + type: string + enum: + - static + - dynamic + description: Defines whether this is a static or dynamic formula. + - type: object + properties: + type: + type: string + enum: + - string + - longform + - options + - number + - boolean + - array + - datetime + - attachment + - link + - formula + - auto + - json + - internal + description: Defines the type of the column, most explain themselves, a link + column is a relationship. + constraints: + type: object + description: A constraint can be applied to the column which will be validated + against when a row is saved. + properties: + type: + type: string + enum: + - string + - number + - object + - boolean + presence: + type: boolean + description: Defines whether the column is required or not. + name: + type: string + description: The name of the column. + autocolumn: + type: boolean + description: Defines whether the column is automatically generated. security: - ApiKeyAuth: [] paths: + /queries/search: + post: + summary: Search for a query based on its name. + tags: + - queries + "/queries/{queryId}": + post: + summary: Execute a query and retrieve its response. + tags: + - queries "/tables/{tableId}/rows/search": post: summary: Used to search for rows within a table. @@ -380,8 +513,8 @@ paths: properties: name: type: string - description: The name of the table, this should be an exact match (ignoring - case). + description: The name of the table, this is a case insensitive search using the + provided name as a starts with search. responses: "200": description: Returns the found tables, based on the search parameters. @@ -420,23 +553,6 @@ paths: examples: table: $ref: "#/components/examples/table" - get: - summary: Get all the tables, internal and external within an app. - tags: - - tables - parameters: - - $ref: "#/components/parameters/tableId" - - $ref: "#/components/parameters/appId" - responses: - "200": - description: Returns all of the tables which were found. - content: - application/json: - schema: - type: object - examples: - table: - $ref: "#/components/examples/row" /tables/:tableId: put: summary: Update the specified table. This can be for internal or external tables. @@ -464,6 +580,23 @@ paths: table: $ref: "#/components/examples/row" "/tables/{tableId}": + get: + summary: Get a single table by its ID, internal and external within an app. + tags: + - tables + parameters: + - $ref: "#/components/parameters/tableId" + - $ref: "#/components/parameters/appId" + responses: + "200": + description: Returns the table that was found. + content: + application/json: + schema: + type: object + examples: + table: + $ref: "#/components/examples/row" delete: summary: Delete a single table and all of its data. tags: diff --git a/packages/server/specs/schemas.js b/packages/server/specs/schemas.js index 1ed31bf0b1..f9fedda89f 100644 --- a/packages/server/specs/schemas.js +++ b/packages/server/specs/schemas.js @@ -1,4 +1,8 @@ -const { FieldTypes } = require("../src/constants") +const { + FieldTypes, + RelationshipTypes, + FormulaTypes, +} = require("../src/constants") exports.row = { description: "The row to be created/updated, based on the table schema.", @@ -14,6 +18,38 @@ exports.row = { }, } +const baseColumnDef = { + type: { + type: "string", + enum: Object.values(FieldTypes), + description: + "Defines the type of the column, most explain themselves, a link column is a relationship.", + }, + constraints: { + type: "object", + description: + "A constraint can be applied to the column which will be validated against when a row is saved.", + properties: { + type: { + type: "string", + enum: ["string", "number", "object", "boolean"], + }, + presence: { + type: "boolean", + description: "Defines whether the column is required or not.", + }, + }, + }, + name: { + type: "string", + description: "The name of the column.", + }, + autocolumn: { + type: "boolean", + description: "Defines whether the column is automatically generated.", + }, +} + exports.table = { description: "The table to be created/updated.", type: "object", @@ -22,17 +58,88 @@ exports.table = { description: "The name of the table", type: "string", }, + primaryDisplay: { + type: "string", + description: + "The name of the column which should be used in relationship tags when relating to this table.", + }, schema: { - type: "object", - additionalProperties: { - type: "object", - properties: { - type: { - type: "string", - enum: Object.values(FieldTypes), + oneOf: [ + // relationship + { + type: "object", + properties: { + ...baseColumnDef, + type: { + type: "string", + enum: [FieldTypes.LINK], + description: "A relationship column.", + }, + fieldName: { + type: "string", + description: + "The name of the column which a relationship column is related to in another table.", + }, + tableId: { + type: "string", + description: + "The ID of the table which a relationship column is related to.", + }, + relationshipType: { + type: "string", + enum: Object.values(RelationshipTypes), + description: + "Defines the type of relationship that this column will be used for.", + }, + through: { + type: "string", + description: + "When using a SQL table that contains many to many relationships this defines the table the relationships are linked through.", + }, + foreignKey: { + type: "string", + description: + "When using a SQL table that contains a one to many relationship this defines the foreign key.", + }, + throughFrom: { + type: "string", + description: + "When using a SQL table that utilises a through table, this defines the primary key in the through table for this table.", + }, + throughTo: { + type: "string", + description: + "When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table.", + }, }, }, - }, + { + type: "object", + properties: { + ...baseColumnDef, + type: { + type: "string", + enum: [FieldTypes.FORMULA], + description: "A formula column.", + }, + formula: { + type: "string", + description: + "Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format.", + }, + formulaType: { + type: "string", + enum: Object.values(FormulaTypes), + description: + "Defines whether this is a static or dynamic formula.", + }, + }, + }, + { + type: "object", + properties: baseColumnDef, + }, + ], }, }, } diff --git a/packages/server/src/api/controllers/public/queries.js b/packages/server/src/api/controllers/public/queries.js new file mode 100644 index 0000000000..781b8414e2 --- /dev/null +++ b/packages/server/src/api/controllers/public/queries.js @@ -0,0 +1,7 @@ +exports.search = () => { + +} + +exports.execute = () => { + +} diff --git a/packages/server/src/api/routes/public/queries.js b/packages/server/src/api/routes/public/queries.js index f9a77e6bc5..113767946b 100644 --- a/packages/server/src/api/routes/public/queries.js +++ b/packages/server/src/api/routes/public/queries.js @@ -1,5 +1,26 @@ const Router = require("@koa/router") +const controller = require("../../controllers/public/queries") const router = Router() +/** + * @openapi + * /queries/search: + * post: + * summary: Search for a query based on its name. + * tags: + * - queries + */ +router.post("/queries/search", controller.search) + +/** + * @openapi + * /queries/{queryId}: + * post: + * summary: Execute a query and retrieve its response. + * tags: + * - queries + */ +router.post("/queries/:queryId", controller.execute) + module.exports = router diff --git a/packages/server/src/api/routes/public/tables.js b/packages/server/src/api/routes/public/tables.js index f245870d33..748a7ca704 100644 --- a/packages/server/src/api/routes/public/tables.js +++ b/packages/server/src/api/routes/public/tables.js @@ -20,7 +20,8 @@ const router = Router() * properties: * name: * type: string - * description: The name of the table, this should be an exact match (ignoring case). + * description: The name of the table, this is a case insensitive search using the provided + * name as a starts with search. * responses: * 200: * description: Returns the found tables, based on the search parameters. @@ -100,9 +101,9 @@ router.put("/tables/:tableId", controller.update) /** * @openapi - * /tables: + * /tables/{tableId}: * get: - * summary: Get all the tables, internal and external within an app. + * summary: Get a single table by its ID, internal and external within an app. * tags: * - tables * parameters: @@ -110,7 +111,7 @@ router.put("/tables/:tableId", controller.update) * - $ref: '#/components/parameters/appId' * responses: * 200: - * description: Returns all of the tables which were found. + * description: Returns the table that was found. * content: * application/json: * schema: @@ -119,7 +120,7 @@ router.put("/tables/:tableId", controller.update) * table: * $ref: '#/components/examples/row' */ -router.get("/tables", controller.singleRead) +router.get("/tables/:tableId", controller.singleRead) /** * @openapi