From 2c5e7690594dd29a3e96dc822407abd287c49a70 Mon Sep 17 00:00:00 2001 From: Marin Minnerly Date: Sun, 4 Feb 2024 13:48:56 -0800 Subject: [PATCH] Create file + tests for parsing the type body --- .../createLuauTypeFromOpenAPIObject.luau | 65 +++---------------- .../createLuauTypeFromOpenAPIObject.spec.luau | 19 ++---- server/src/openapi/parseTypeBody.luau | 46 +++++++++++++ server/src/openapi/parseTypeBody.spec.luau | 17 +++++ server/src/openapi/types.luau | 2 + 5 files changed, 80 insertions(+), 69 deletions(-) create mode 100644 server/src/openapi/parseTypeBody.luau create mode 100644 server/src/openapi/parseTypeBody.spec.luau diff --git a/server/src/openapi/createLuauTypeFromOpenAPIObject.luau b/server/src/openapi/createLuauTypeFromOpenAPIObject.luau index 2bb2166..4ce9c4e 100644 --- a/server/src/openapi/createLuauTypeFromOpenAPIObject.luau +++ b/server/src/openapi/createLuauTypeFromOpenAPIObject.luau @@ -1,76 +1,27 @@ local types = require("@server/openapi/types") +local parseTypeBody = require("@server/openapi/parseTypeBody") local createLuauComment = require("@server/openapi/createLuauComment") type Object = types.Object -local function createTypePropertiesFromObject(object: Object): Object> - local inner = {} - - if object.type and object.type == "object" and object.properties then - for key, value in object.properties do - local valueType = typeof(value) - - if valueType == "table" then - value = createTypePropertiesFromObject(value) - end - - if object.required then - local isRequired = table.find(object.required, key) - -- TODO: Determine if properties in OpenAPI objects are required - -- by default - if isRequired == false then - valueType ..= "?" - end - end - - inner[key] = valueType - end - end - - return inner -end - -local function createLuauTypeFromOpenAPIObject(object: Object): types.LuauType - local comment = createLuauComment(object) - - print(object) +local function createLuauTypeFromOpenAPIObject(name: string, object: Object): types.LuauType + local body if object.type == "object" then - local properties = {} + body = {} if object.properties then for key, value in object.properties do - print(key, value) - if typeof(value) == "table" then - value = createTypePropertiesFromObject(value) - else - value = typeof(value) - end - properties[key] = value + body[key] = parseTypeBody(value) end end - local inner = table.concat(properties, "\n") - - print("properties", properties) - - return properties - - -- local typeString = `export type {name} = \{{inner}\}` - -- if comment then - -- return `{comment}\n{typeString}` - -- else - -- return typeString - -- end elseif object.type == "integer" then - return "number" + body = "number" else - return { - comment = comment, - source = typeof(object), - } + body = object.type end return { - name = name, + body = body, comment = createLuauComment(object), } end diff --git a/server/src/openapi/createLuauTypeFromOpenAPIObject.spec.luau b/server/src/openapi/createLuauTypeFromOpenAPIObject.spec.luau index 65ff1a2..d7843e7 100644 --- a/server/src/openapi/createLuauTypeFromOpenAPIObject.spec.luau +++ b/server/src/openapi/createLuauTypeFromOpenAPIObject.spec.luau @@ -13,26 +13,21 @@ assert(petstore.components.schemas, "no schemas found in mock API") -- print("schemas", petstore.components.schemas) -local Pet = createLuauTypeFromOpenAPIObject(petstore.components.schemas.Pet) +local Pet = createLuauTypeFromOpenAPIObject("Pet", petstore.components.schemas.Pet) assert(Pet ~= nil, `missing "Pet" schema`) -assert(Pet.id == "number", `bad Pet.id (expected number, got {Pet.id})`) -assert(Pet.name == "string", `bad Pet.name (expected string, got {Pet.name})`) -assert(Pet.tag == "string?", `bad Pet.tag (expected string?, got {Pet.tag})`) +assert(Pet.body ~= nil, `bad Pet.body (expected table, got {Pet.body})`) +assert(Pet.body.id == "number", `bad Pet.body.id (expected number, got {Pet.body.id})`) +assert(Pet.body.name == "string", `bad Pet.body.name (expected string, got {Pet.body.name})`) +assert(Pet.body.tag == "string?", `bad Pet.body.tag (expected string?, got {Pet.body.tag})`) -local Pets = createLuauTypeFromOpenAPIObject(petstore.components.schemas.Pets) +local Pets = createLuauTypeFromOpenAPIObject("Pets", petstore.components.schemas.Pets) assert(Pets ~= nil, `missing "Pets" schema`) assert(Pets.id == "number", `bad Pets.id (expected number, got {Pets.id})`) assert(Pets.name == "string", `bad Pets.name (expected string, got {Pets.name})`) assert(Pets.tag == "string?", `bad Pets.tag (expected string?, got {Pets.tag})`) -local Error = createLuauTypeFromOpenAPIObject(petstore.components.schemas.Error) +local Error = createLuauTypeFromOpenAPIObject("Error", petstore.components.schemas.Error) assert(Error, `missing "Error" schema`) -- assert(nil, "summary is not included in type comment") -- assert(nil, "description is not included in type comment") - -assert(petstore.components.responses, "no responses found in mock API") - -local responses = createLuauTypeFromOpenAPIObject(petstore.components.responses) - -print(responses) diff --git a/server/src/openapi/parseTypeBody.luau b/server/src/openapi/parseTypeBody.luau new file mode 100644 index 0000000..2972d62 --- /dev/null +++ b/server/src/openapi/parseTypeBody.luau @@ -0,0 +1,46 @@ +local types = require("@server/openapi/types") + +type Object = types.Object + +local function parseTypeBody(object: Object): Object> + local body = {} + + if object.type then + if object.type == "object" then + if object.properties then + for key, value in object.properties do + local valueType = typeof(value) + + if valueType == "table" then + valueType = parseTypeBody(value) + end + + -- TODO: Handle refs + + if object.required then + local isRequired = table.find(object.required, key) + -- TODO: Check if properties in OpenAPI objects are required by + -- default. Right now the assumption is that they are + if not isRequired then + valueType ..= "?" + end + end + + body[key] = valueType + end + else + body = "{ [string]: any }" + end + else + if object.type == "integer" then + body = "number" + else + body = object.type + end + end + end + + return body +end + +return parseTypeBody diff --git a/server/src/openapi/parseTypeBody.spec.luau b/server/src/openapi/parseTypeBody.spec.luau new file mode 100644 index 0000000..6a12ff2 --- /dev/null +++ b/server/src/openapi/parseTypeBody.spec.luau @@ -0,0 +1,17 @@ +local fs = require("@lune/fs") +local serde = require("@lune/serde") +local openapiTypes = require("@server/openapi/openapi31") +local parseTypeBody = require("./parseTypeBody") + +type OpenAPIObject = openapiTypes.OpenAPIObject + +local petstore: OpenAPIObject = serde.decode("yaml", fs.readFile("server/src/openapi/mocks/petstore.yml")) + +local body = parseTypeBody(petstore.components.schemas.Pet) +assert(body ~= nil, `bad body (expected table, got {body})`) +assert(body.id == "number", `bad body.id (expected number, got {body.id})`) +assert(body.name == "string", `bad body.name (expected string, got {body.name})`) +assert(body.tag == "string?", `bad body.tag (expected string?, got {body.tag})`) + +body = parseTypeBody(petstore.components.schemas.Pets) +assert(body ~= nil, `bad body (expected table, got {body})`) diff --git a/server/src/openapi/types.luau b/server/src/openapi/types.luau index b24d09b..ab7850b 100644 --- a/server/src/openapi/types.luau +++ b/server/src/openapi/types.luau @@ -1,5 +1,7 @@ export type Object = { [string]: T } +type Primitive = string | number | boolean + export type LuauType = { name: string, body: Primitive | { [string]: Primitive },