mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
465 lines
13 KiB
Lua
465 lines
13 KiB
Lua
-- Package template definitions
|
|
-- @module package_template.templates
|
|
|
|
local M = {}
|
|
|
|
---@return string[] Available package categories
|
|
function M.get_categories()
|
|
return {
|
|
"ui",
|
|
"editors",
|
|
"tools",
|
|
"social",
|
|
"media",
|
|
"gaming",
|
|
"admin",
|
|
"config",
|
|
"core",
|
|
"demo",
|
|
"development",
|
|
"managers"
|
|
}
|
|
end
|
|
|
|
---Generate metadata.json content
|
|
---@param config PackageConfig
|
|
---@return string JSON content
|
|
function M.generate_metadata(config)
|
|
local metadata = {
|
|
packageId = config.packageId,
|
|
name = config.name,
|
|
version = "1.0.0",
|
|
description = config.description,
|
|
icon = "static_content/icon.svg",
|
|
author = config.author or "MetaBuilder",
|
|
category = config.category,
|
|
primary = config.primary,
|
|
dependencies = config.dependencies or {},
|
|
devDependencies = { "lua_test" },
|
|
exports = {
|
|
components = config.components or {},
|
|
scripts = { "init" }
|
|
},
|
|
tests = {
|
|
scripts = { "tests/metadata.test.lua", "tests/components.test.lua" },
|
|
cases = { "tests/metadata.cases.json", "tests/components.cases.json" }
|
|
},
|
|
minLevel = config.minLevel
|
|
}
|
|
|
|
-- Add schema if requested
|
|
if config.withSchema and config.entities and #config.entities > 0 then
|
|
metadata.schema = {
|
|
entities = config.entities,
|
|
path = "schema/entities.yaml"
|
|
}
|
|
end
|
|
|
|
-- Add permissions
|
|
if config.permissions then
|
|
metadata.permissions = {}
|
|
for permKey, permConfig in pairs(config.permissions) do
|
|
metadata.permissions[permKey] = {
|
|
minLevel = permConfig.minLevel,
|
|
description = permConfig.description
|
|
}
|
|
end
|
|
else
|
|
-- Generate default permissions based on package type
|
|
metadata.permissions = M.generate_default_permissions(config)
|
|
end
|
|
|
|
return M.to_json(metadata)
|
|
end
|
|
|
|
---Generate default permissions based on package config
|
|
---@param config PackageConfig
|
|
---@return table<string, table>
|
|
function M.generate_default_permissions(config)
|
|
local prefix = string.gsub(config.packageId, "_", ".")
|
|
local permissions = {}
|
|
|
|
-- Basic view permission
|
|
permissions[prefix .. ".view"] = {
|
|
minLevel = config.minLevel,
|
|
description = "View " .. config.name
|
|
}
|
|
|
|
-- If primary, add more permissions
|
|
if config.primary then
|
|
permissions[prefix .. ".edit"] = {
|
|
minLevel = config.minLevel,
|
|
description = "Edit " .. config.name .. " content"
|
|
}
|
|
end
|
|
|
|
-- If has schema, add CRUD permissions
|
|
if config.withSchema and config.entities then
|
|
for _, entity in ipairs(config.entities) do
|
|
local entityLower = string.lower(entity)
|
|
permissions[prefix .. "." .. entityLower .. ".create"] = {
|
|
minLevel = config.minLevel,
|
|
description = "Create " .. entity
|
|
}
|
|
permissions[prefix .. "." .. entityLower .. ".update"] = {
|
|
minLevel = config.minLevel,
|
|
description = "Update " .. entity
|
|
}
|
|
permissions[prefix .. "." .. entityLower .. ".delete"] = {
|
|
minLevel = math.min(config.minLevel + 1, 6),
|
|
description = "Delete " .. entity
|
|
}
|
|
end
|
|
end
|
|
|
|
return permissions
|
|
end
|
|
|
|
---Generate init.lua content
|
|
---@param config PackageConfig
|
|
---@return string Lua content
|
|
function M.generate_init_lua(config)
|
|
local lines = {
|
|
"--- " .. config.name .. " initialization",
|
|
"--- @module init",
|
|
"",
|
|
"local M = {}",
|
|
"",
|
|
"---@class InstallContext",
|
|
"---@field version string",
|
|
"",
|
|
"---@class InstallResult",
|
|
"---@field message string",
|
|
"---@field version string",
|
|
"",
|
|
"---Called when package is installed",
|
|
"---@param context InstallContext",
|
|
"---@return InstallResult",
|
|
"function M.on_install(context)",
|
|
" return {",
|
|
" message = \"" .. config.name .. " installed successfully\",",
|
|
" version = context.version",
|
|
" }",
|
|
"end",
|
|
"",
|
|
"---Called when package is uninstalled",
|
|
"---@return table",
|
|
"function M.on_uninstall()",
|
|
" return { message = \"" .. config.name .. " removed\" }",
|
|
"end",
|
|
"",
|
|
"return M"
|
|
}
|
|
return table.concat(lines, "\n")
|
|
end
|
|
|
|
---Generate component.json entry
|
|
---@param componentName string
|
|
---@param config PackageConfig
|
|
---@return table Component definition
|
|
function M.generate_component(componentName, config)
|
|
local componentId = string.lower(config.packageId .. "_" .. componentName)
|
|
|
|
return {
|
|
id = componentId,
|
|
type = "container",
|
|
name = componentName,
|
|
description = componentName .. " component for " .. config.name,
|
|
props = {},
|
|
layout = {
|
|
type = "flex",
|
|
props = {
|
|
direction = "column",
|
|
gap = 2
|
|
}
|
|
},
|
|
bindings = {}
|
|
}
|
|
end
|
|
|
|
---Generate components.json content
|
|
---@param config PackageConfig
|
|
---@return string JSON content
|
|
function M.generate_components_json(config)
|
|
local components = {}
|
|
|
|
if config.components then
|
|
for _, name in ipairs(config.components) do
|
|
table.insert(components, M.generate_component(name, config))
|
|
end
|
|
end
|
|
|
|
return M.to_json(components)
|
|
end
|
|
|
|
---Generate test file content
|
|
---@param testName string Test name
|
|
---@param config PackageConfig
|
|
---@return string Lua test content
|
|
function M.generate_test(testName, config)
|
|
local lines = {
|
|
"-- " .. testName .. " tests for " .. config.packageId,
|
|
"",
|
|
"describe(\"" .. config.name .. " - " .. testName .. "\", function()",
|
|
" it(\"should pass basic validation\", function()",
|
|
" expect(true).toBe(true)",
|
|
" end)",
|
|
"",
|
|
" it(\"should have required fields\", function()",
|
|
" -- TODO: Add specific tests",
|
|
" expect(true).toBe(true)",
|
|
" end)",
|
|
"end)",
|
|
""
|
|
}
|
|
return table.concat(lines, "\n")
|
|
end
|
|
|
|
---Generate test cases JSON
|
|
---@param testName string
|
|
---@return string JSON content
|
|
function M.generate_test_cases(testName)
|
|
local cases = {
|
|
{
|
|
name = "valid_input",
|
|
input = {},
|
|
expected = { valid = true }
|
|
},
|
|
{
|
|
name = "invalid_input",
|
|
input = { invalid = true },
|
|
expected = { valid = false }
|
|
}
|
|
}
|
|
return M.to_json(cases)
|
|
end
|
|
|
|
---Generate schema YAML content
|
|
---@param config PackageConfig
|
|
---@return string YAML content
|
|
function M.generate_schema_yaml(config)
|
|
if not config.entities or #config.entities == 0 then
|
|
return "# No entities defined\n"
|
|
end
|
|
|
|
local lines = {
|
|
"# " .. config.name .. " Entity Definitions",
|
|
"# Auto-generated by package template generator",
|
|
""
|
|
}
|
|
|
|
for _, entity in ipairs(config.entities) do
|
|
local prefixedEntity = "Pkg_" .. M.to_pascal_case(config.packageId) .. "_" .. entity
|
|
table.insert(lines, prefixedEntity .. ":")
|
|
table.insert(lines, " description: \"" .. entity .. " entity for " .. config.name .. "\"")
|
|
table.insert(lines, " fields:")
|
|
table.insert(lines, " id:")
|
|
table.insert(lines, " type: string")
|
|
table.insert(lines, " primary: true")
|
|
table.insert(lines, " tenantId:")
|
|
table.insert(lines, " type: string")
|
|
table.insert(lines, " required: true")
|
|
table.insert(lines, " index: true")
|
|
table.insert(lines, " createdAt:")
|
|
table.insert(lines, " type: datetime")
|
|
table.insert(lines, " default: now")
|
|
table.insert(lines, " updatedAt:")
|
|
table.insert(lines, " type: datetime")
|
|
table.insert(lines, " onUpdate: now")
|
|
table.insert(lines, " # TODO: Add entity-specific fields")
|
|
table.insert(lines, "")
|
|
end
|
|
|
|
return table.concat(lines, "\n")
|
|
end
|
|
|
|
---Generate layout.json content
|
|
---@param config PackageConfig
|
|
---@return string JSON content
|
|
function M.generate_layout_json(config)
|
|
local layout = {
|
|
id = config.packageId .. "_layout",
|
|
name = config.name .. " Layout",
|
|
type = "page",
|
|
props = {
|
|
title = config.name,
|
|
minLevel = config.minLevel
|
|
},
|
|
children = {}
|
|
}
|
|
|
|
-- Add header section
|
|
table.insert(layout.children, {
|
|
id = config.packageId .. "_header",
|
|
type = "container",
|
|
props = { variant = "header" },
|
|
children = {
|
|
{
|
|
id = config.packageId .. "_title",
|
|
type = "text",
|
|
props = { variant = "h1", content = config.name }
|
|
},
|
|
{
|
|
id = config.packageId .. "_description",
|
|
type = "text",
|
|
props = { variant = "body1", content = config.description }
|
|
}
|
|
}
|
|
})
|
|
|
|
-- Add main content section
|
|
table.insert(layout.children, {
|
|
id = config.packageId .. "_content",
|
|
type = "container",
|
|
props = { variant = "main" },
|
|
children = {
|
|
{
|
|
id = config.packageId .. "_placeholder",
|
|
type = "text",
|
|
props = { content = "Add your components here" }
|
|
}
|
|
}
|
|
})
|
|
|
|
return M.to_json(layout)
|
|
end
|
|
|
|
---Generate icon SVG
|
|
---@param config PackageConfig
|
|
---@return string SVG content
|
|
function M.generate_icon_svg(config)
|
|
-- Get first letter of package name for icon
|
|
local letter = string.upper(string.sub(config.name, 1, 1))
|
|
|
|
return [[<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
|
|
<text x="12" y="16" text-anchor="middle" font-size="12" fill="currentColor" stroke="none">]] .. letter .. [[</text>
|
|
</svg>]]
|
|
end
|
|
|
|
---Generate README.md content
|
|
---@param config PackageConfig
|
|
---@return string Markdown content
|
|
function M.generate_readme(config)
|
|
local lines = {
|
|
"# " .. config.name,
|
|
"",
|
|
config.description,
|
|
"",
|
|
"## Installation",
|
|
"",
|
|
"This package is part of the MetaBuilder platform and is installed automatically.",
|
|
"",
|
|
"## Access Level",
|
|
"",
|
|
"Minimum level required: **" .. config.minLevel .. "**",
|
|
"",
|
|
}
|
|
|
|
if config.primary then
|
|
table.insert(lines, "This is a **primary package** that can own routes.")
|
|
else
|
|
table.insert(lines, "This is a **dependency package** that provides shared functionality.")
|
|
end
|
|
table.insert(lines, "")
|
|
|
|
if config.withSchema and config.entities and #config.entities > 0 then
|
|
table.insert(lines, "## Entities")
|
|
table.insert(lines, "")
|
|
for _, entity in ipairs(config.entities) do
|
|
table.insert(lines, "- " .. entity)
|
|
end
|
|
table.insert(lines, "")
|
|
end
|
|
|
|
if config.components and #config.components > 0 then
|
|
table.insert(lines, "## Components")
|
|
table.insert(lines, "")
|
|
for _, comp in ipairs(config.components) do
|
|
table.insert(lines, "- `" .. comp .. "`")
|
|
end
|
|
table.insert(lines, "")
|
|
end
|
|
|
|
table.insert(lines, "## Development")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "```bash")
|
|
table.insert(lines, "# Run tests")
|
|
table.insert(lines, "npm run test:package " .. config.packageId)
|
|
table.insert(lines, "```")
|
|
table.insert(lines, "")
|
|
|
|
return table.concat(lines, "\n")
|
|
end
|
|
|
|
---Convert table to JSON string (simple implementation)
|
|
---@param tbl table
|
|
---@return string
|
|
function M.to_json(tbl)
|
|
-- Use the global json if available, otherwise simple stringify
|
|
if json and json.encode then
|
|
return json.encode(tbl)
|
|
end
|
|
|
|
-- Simple fallback - in real usage would use proper JSON library
|
|
return M.stringify(tbl, 0)
|
|
end
|
|
|
|
---Simple table to JSON string converter
|
|
---@param val any
|
|
---@param indent number
|
|
---@return string
|
|
function M.stringify(val, indent)
|
|
local t = type(val)
|
|
|
|
if t == "nil" then
|
|
return "null"
|
|
elseif t == "boolean" then
|
|
return val and "true" or "false"
|
|
elseif t == "number" then
|
|
return tostring(val)
|
|
elseif t == "string" then
|
|
return '"' .. val:gsub('"', '\\"'):gsub('\n', '\\n') .. '"'
|
|
elseif t == "table" then
|
|
local spaces = string.rep(" ", indent)
|
|
local nextSpaces = string.rep(" ", indent + 1)
|
|
|
|
-- Check if array
|
|
local isArray = #val > 0 or next(val) == nil
|
|
if isArray then
|
|
local items = {}
|
|
for i, v in ipairs(val) do
|
|
table.insert(items, nextSpaces .. M.stringify(v, indent + 1))
|
|
end
|
|
if #items == 0 then
|
|
return "[]"
|
|
end
|
|
return "[\n" .. table.concat(items, ",\n") .. "\n" .. spaces .. "]"
|
|
else
|
|
local items = {}
|
|
for k, v in pairs(val) do
|
|
table.insert(items, nextSpaces .. '"' .. tostring(k) .. '": ' .. M.stringify(v, indent + 1))
|
|
end
|
|
if #items == 0 then
|
|
return "{}"
|
|
end
|
|
return "{\n" .. table.concat(items, ",\n") .. "\n" .. spaces .. "}"
|
|
end
|
|
end
|
|
|
|
return "null"
|
|
end
|
|
|
|
---Convert string to PascalCase
|
|
---@param str string
|
|
---@return string
|
|
function M.to_pascal_case(str)
|
|
local result = ""
|
|
for word in string.gmatch(str, "[^_]+") do
|
|
result = result .. string.upper(string.sub(word, 1, 1)) .. string.sub(word, 2)
|
|
end
|
|
return result
|
|
end
|
|
|
|
return M
|