Created
March 8, 2024 21:04
-
-
Save Totktonada/5a310dfee015e8ac68fb01c066f8c222 to your computer and use it in GitHub Desktop.
Generate JSON schema for Tarantool's cluster configuration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env tarantool | |
local json = require('json') | |
local cluster_config = require('internal.config.cluster_config') | |
local scalars = {} | |
scalars.string = { | |
jsonschema = { | |
type = 'string', | |
}, | |
} | |
scalars.number = { | |
jsonschema = { | |
type = 'number', | |
}, | |
} | |
scalars['string, number'] = { | |
jsonschema = { | |
type = {'string', 'number'}, | |
}, | |
} | |
scalars['number, string'] = { | |
jsonschema = { | |
type = {'string', 'number'}, | |
}, | |
} | |
scalars.integer = { | |
jsonschema = { | |
type = 'integer', | |
}, | |
} | |
scalars.boolean = { | |
jsonschema = { | |
type = 'boolean', | |
}, | |
} | |
scalars.any = { | |
jsonschema = {}, | |
} | |
local function is_scalar(schema) | |
return scalars[schema.type] ~= nil | |
end | |
local function extract_validate_no_repeat() | |
local schema = require('internal.config.utils.schema') | |
local nups = debug.getinfo(schema.set).nups | |
for i = 1, nups do | |
local k, v = debug.getupvalue(schema.set, i) | |
if k == 'validate_no_repeat' then | |
return v | |
end | |
end | |
end | |
local validate_no_repeat = extract_validate_no_repeat() | |
assert(type(validate_no_repeat) == 'function') | |
local function set_common_fields(res, schema) | |
-- Ignores apply_default_if. | |
res.default = schema.default | |
res.enum = schema.allowed_values | |
return setmetatable(res, { | |
__serialize = 'map', | |
}) | |
end | |
local function traverse_impl(schema) | |
if is_scalar(schema) then | |
local scalar_def = scalars[schema.type] | |
assert(scalar_def ~= nil) | |
return set_common_fields(table.copy(scalar_def.jsonschema), schema) | |
elseif schema.type == 'record' then | |
local properties = {} | |
for field_name, field_def in pairs(schema.fields) do | |
properties[field_name] = traverse_impl(field_def) | |
end | |
return set_common_fields({ | |
type = 'object', | |
properties = properties, | |
additionalProperties = false, | |
}, schema) | |
elseif schema.type == 'map' then | |
assert(schema.key.type == 'string') | |
return set_common_fields({ | |
type = 'object', | |
additionalProperties = traverse_impl(schema.value), | |
}, schema) | |
elseif schema.type == 'array' then | |
local res = { | |
type = 'array', | |
items = traverse_impl(schema.items), | |
} | |
if schema.validate == validate_no_repeat then | |
res.uniqueItems = true | |
end | |
return set_common_fields(res, schema) | |
else | |
assert(false) | |
end | |
end | |
local function traverse(schema_obj) | |
local res = traverse_impl(rawget(schema_obj, 'schema')) | |
res['$schema'] = 'https://json-schema.org/draft/2020-12/schema' | |
return res | |
end | |
local jsonschema = traverse(cluster_config) | |
print(json.encode(jsonschema)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment