From ea6bd1c69ae77fd6db528e09b306ae9ff2f761e4 Mon Sep 17 00:00:00 2001 From: Richard Ward Date: Tue, 30 Dec 2025 13:15:23 +0000 Subject: [PATCH] update: packages,lua,log (12 files) --- .../scripts/formatting/format_all_logs.lua | 19 +++++ .../scripts/formatting/format_log_entry.lua | 30 ++++++++ .../scripts/formatting/format_timestamp.lua | 19 +++++ .../formatting/get_operation_color.lua | 15 ++++ .../scripts/formatting/get_resource_icon.lua | 15 ++++ .../scripts/formatting/get_status_badge.lua | 16 +++++ .../seed/scripts/formatting/init.lua | 34 +++++++++ .../seed/scripts/formatting/mappings.lua | 23 ++++++ .../seed/scripts/formatting/types.lua | 28 ++++++++ .../seed/scripts/tests/fields.test.lua | 70 +++++++++++++++++++ .../seed/scripts/tests/relations.test.lua | 69 ++++++++++++++++++ .../seed/scripts/tests/tables.test.lua | 61 ++++++++++++++++ 12 files changed, 399 insertions(+) create mode 100644 packages/audit_log/seed/scripts/formatting/format_all_logs.lua create mode 100644 packages/audit_log/seed/scripts/formatting/format_log_entry.lua create mode 100644 packages/audit_log/seed/scripts/formatting/format_timestamp.lua create mode 100644 packages/audit_log/seed/scripts/formatting/get_operation_color.lua create mode 100644 packages/audit_log/seed/scripts/formatting/get_resource_icon.lua create mode 100644 packages/audit_log/seed/scripts/formatting/get_status_badge.lua create mode 100644 packages/audit_log/seed/scripts/formatting/init.lua create mode 100644 packages/audit_log/seed/scripts/formatting/mappings.lua create mode 100644 packages/audit_log/seed/scripts/formatting/types.lua create mode 100644 packages/schema_editor/seed/scripts/tests/fields.test.lua create mode 100644 packages/schema_editor/seed/scripts/tests/relations.test.lua create mode 100644 packages/schema_editor/seed/scripts/tests/tables.test.lua diff --git a/packages/audit_log/seed/scripts/formatting/format_all_logs.lua b/packages/audit_log/seed/scripts/formatting/format_all_logs.lua new file mode 100644 index 000000000..d19824e17 --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/format_all_logs.lua @@ -0,0 +1,19 @@ +-- Format all logs for display + +local formatLogEntry = require("formatting.format_log_entry") + +---@class FormatAllLogs +local M = {} + +---Format all logs in an array for display +---@param logs AuditLog[]? Array of raw log entries +---@return FormattedLogEntry[] Array of formatted entries +function M.formatAllLogs(logs) + local result = {} + for i, log in ipairs(logs or {}) do + result[i] = formatLogEntry.formatLogEntry(log) + end + return result +end + +return M diff --git a/packages/audit_log/seed/scripts/formatting/format_log_entry.lua b/packages/audit_log/seed/scripts/formatting/format_log_entry.lua new file mode 100644 index 000000000..527bac636 --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/format_log_entry.lua @@ -0,0 +1,30 @@ +-- Format a single log entry for display + +local getOperationColor = require("formatting.get_operation_color") +local getResourceIcon = require("formatting.get_resource_icon") +local formatTimestamp = require("formatting.format_timestamp") + +---@class FormatLogEntry +local M = {} + +---Format a log entry for display in a table +---@param log AuditLog Raw log entry +---@return FormattedLogEntry Formatted entry with display strings +function M.formatLogEntry(log) + return { + id = log.id, + operation = log.operation, + operationColor = getOperationColor.getOperationColor(log.operation), + resource = log.resource, + resourceId = log.resourceId, + resourceIcon = getResourceIcon.getResourceIcon(log.resource), + username = log.username, + timestamp = formatTimestamp.formatTimestamp(log.timestamp), + ipAddress = log.ipAddress, + success = log.success, + errorMessage = log.errorMessage, + rowClass = log.success and "bg-card" or "bg-destructive/5 border-destructive/20" + } +end + +return M diff --git a/packages/audit_log/seed/scripts/formatting/format_timestamp.lua b/packages/audit_log/seed/scripts/formatting/format_timestamp.lua new file mode 100644 index 000000000..0d58d3bef --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/format_timestamp.lua @@ -0,0 +1,19 @@ +-- Format timestamp for display + +---@class FormatTimestamp +local M = {} + +---Format a timestamp (in milliseconds) for display +---@param timestamp number? Unix timestamp in milliseconds +---@return string Formatted date/time string or "Unknown" +function M.formatTimestamp(timestamp) + if not timestamp then + return "Unknown" + end + + -- Assuming timestamp is in milliseconds + local seconds = math.floor(timestamp / 1000) + return os.date("%Y-%m-%d %H:%M:%S", seconds) +end + +return M diff --git a/packages/audit_log/seed/scripts/formatting/get_operation_color.lua b/packages/audit_log/seed/scripts/formatting/get_operation_color.lua new file mode 100644 index 000000000..837c041dc --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/get_operation_color.lua @@ -0,0 +1,15 @@ +-- Get color class for operation type + +local mappings = require("formatting.mappings") + +---@class GetOperationColor +local M = {} + +---Get CSS color class for an operation type +---@param operation string Operation name (CREATE, READ, UPDATE, DELETE) +---@return string CSS class for the operation badge +function M.getOperationColor(operation) + return mappings.operationColors[operation] or "bg-gray-500" +end + +return M diff --git a/packages/audit_log/seed/scripts/formatting/get_resource_icon.lua b/packages/audit_log/seed/scripts/formatting/get_resource_icon.lua new file mode 100644 index 000000000..f206a5bae --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/get_resource_icon.lua @@ -0,0 +1,15 @@ +-- Get icon name for resource type + +local mappings = require("formatting.mappings") + +---@class GetResourceIcon +local M = {} + +---Get icon name for a resource type +---@param resource string Resource type name +---@return string Icon name for the resource +function M.getResourceIcon(resource) + return mappings.resourceIcons[resource] or mappings.resourceIcons.default +end + +return M diff --git a/packages/audit_log/seed/scripts/formatting/get_status_badge.lua b/packages/audit_log/seed/scripts/formatting/get_status_badge.lua new file mode 100644 index 000000000..023bf2559 --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/get_status_badge.lua @@ -0,0 +1,16 @@ +-- Get status badge text for a log + +---@class GetStatusBadge +local M = {} + +---Get status badge text for a log entry +---@param log AuditLog Log entry to check +---@return string? Badge text or nil if successful +function M.getStatusBadge(log) + if log.success then + return nil + end + return "Failed" +end + +return M diff --git a/packages/audit_log/seed/scripts/formatting/init.lua b/packages/audit_log/seed/scripts/formatting/init.lua new file mode 100644 index 000000000..b5de20848 --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/init.lua @@ -0,0 +1,34 @@ +-- Audit log formatting module +-- Facade that re-exports all formatting functions + +local mappings = require("formatting.mappings") +local getOperationColor = require("formatting.get_operation_color") +local getResourceIcon = require("formatting.get_resource_icon") +local formatTimestamp = require("formatting.format_timestamp") +local formatLogEntry = require("formatting.format_log_entry") +local formatAllLogs = require("formatting.format_all_logs") +local getStatusBadge = require("formatting.get_status_badge") + +---@class FormattingModule +---@field operationColors table +---@field resourceIcons table +---@field getOperationColor fun(operation: string): string +---@field getResourceIcon fun(resource: string): string +---@field formatTimestamp fun(timestamp: number?): string +---@field formatLogEntry fun(log: AuditLog): FormattedLogEntry +---@field formatAllLogs fun(logs: AuditLog[]?): FormattedLogEntry[] +---@field getStatusBadge fun(log: AuditLog): string? + +---@type FormattingModule +local M = { + operationColors = mappings.operationColors, + resourceIcons = mappings.resourceIcons, + getOperationColor = getOperationColor.getOperationColor, + getResourceIcon = getResourceIcon.getResourceIcon, + formatTimestamp = formatTimestamp.formatTimestamp, + formatLogEntry = formatLogEntry.formatLogEntry, + formatAllLogs = formatAllLogs.formatAllLogs, + getStatusBadge = getStatusBadge.getStatusBadge, +} + +return M diff --git a/packages/audit_log/seed/scripts/formatting/mappings.lua b/packages/audit_log/seed/scripts/formatting/mappings.lua new file mode 100644 index 000000000..f7b0f1de2 --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/mappings.lua @@ -0,0 +1,23 @@ +-- Color and icon mappings for audit log display + +---@class Mappings +local M = {} + +--- Operation type to color mapping +---@type table +M.operationColors = { + CREATE = "bg-green-500", + READ = "bg-blue-500", + UPDATE = "bg-yellow-500", + DELETE = "bg-red-500" +} + +--- Resource type to icon mapping +---@type table +M.resourceIcons = { + user = "User", + credential = "ShieldCheck", + default = "ChartLine" +} + +return M diff --git a/packages/audit_log/seed/scripts/formatting/types.lua b/packages/audit_log/seed/scripts/formatting/types.lua new file mode 100644 index 000000000..be190d1e4 --- /dev/null +++ b/packages/audit_log/seed/scripts/formatting/types.lua @@ -0,0 +1,28 @@ +-- Shared types for audit log formatting + +---@class AuditLog +---@field id string Unique log entry ID +---@field operation string Operation type (create, read, update, delete) +---@field resource string Resource type being accessed +---@field resourceId string ID of the resource +---@field username string User who performed the action +---@field timestamp number Unix timestamp in milliseconds +---@field ipAddress string IP address of the request +---@field success boolean Whether the operation succeeded +---@field errorMessage string? Error message if failed + +---@class FormattedLogEntry +---@field id string +---@field operation string +---@field operationColor string CSS class for operation badge +---@field resource string +---@field resourceId string +---@field resourceIcon string Icon name for resource type +---@field username string +---@field timestamp string Formatted date/time string +---@field ipAddress string +---@field success boolean +---@field errorMessage string? +---@field rowClass string CSS class for table row + +return {} diff --git a/packages/schema_editor/seed/scripts/tests/fields.test.lua b/packages/schema_editor/seed/scripts/tests/fields.test.lua new file mode 100644 index 000000000..53bb064c0 --- /dev/null +++ b/packages/schema_editor/seed/scripts/tests/fields.test.lua @@ -0,0 +1,70 @@ +-- Fields tests for schema_editor package +-- Tests field type builders + +local string_field = require("fields/string") +local number_field = require("fields/number") +local boolean_field = require("fields/boolean") +local array_field = require("fields/array") + +describe("Schema Field Builders", function() + describe("string_field", function() + it.each({ + { name = "email", required = nil, min = nil, max = nil, expectedRequired = false }, + { name = "username", required = true, min = 3, max = 20, expectedRequired = true }, + })("should create string field $name", function(testCase) + local result = string_field(testCase.name, testCase.required, testCase.min, testCase.max) + expect(result.type).toBe("string") + expect(result.name).toBe(testCase.name) + expect(result.required).toBe(testCase.expectedRequired) + if testCase.min then + expect(result.minLength).toBe(testCase.min) + end + if testCase.max then + expect(result.maxLength).toBe(testCase.max) + end + end) + end) + + describe("number_field", function() + it.each({ + { name = "age", required = nil, min = nil, max = nil, expectedRequired = false }, + { name = "quantity", required = true, min = 0, max = 1000, expectedRequired = true }, + })("should create number field $name", function(testCase) + local result = number_field(testCase.name, testCase.required, testCase.min, testCase.max) + expect(result.type).toBe("number") + expect(result.name).toBe(testCase.name) + expect(result.required).toBe(testCase.expectedRequired) + if testCase.min then + expect(result.min).toBe(testCase.min) + end + if testCase.max then + expect(result.max).toBe(testCase.max) + end + end) + end) + + describe("boolean_field", function() + it.each({ + { name = "active", required = nil, default = nil, expectedRequired = false }, + { name = "verified", required = true, default = false, expectedRequired = true }, + })("should create boolean field $name", function(testCase) + local result = boolean_field(testCase.name, testCase.required, testCase.default) + expect(result.type).toBe("boolean") + expect(result.name).toBe(testCase.name) + expect(result.required).toBe(testCase.expectedRequired) + end) + end) + + describe("array_field", function() + it.each({ + { name = "tags", itemType = "string", required = nil, expectedRequired = false }, + { name = "ids", itemType = "number", required = true, expectedRequired = true }, + })("should create array field $name of $itemType", function(testCase) + local result = array_field(testCase.name, testCase.itemType, testCase.required) + expect(result.type).toBe("array") + expect(result.name).toBe(testCase.name) + expect(result.items.type).toBe(testCase.itemType) + expect(result.required).toBe(testCase.expectedRequired) + end) + end) +end) diff --git a/packages/schema_editor/seed/scripts/tests/relations.test.lua b/packages/schema_editor/seed/scripts/tests/relations.test.lua new file mode 100644 index 000000000..bcf69c3f3 --- /dev/null +++ b/packages/schema_editor/seed/scripts/tests/relations.test.lua @@ -0,0 +1,69 @@ +-- Relations tests for schema_editor package +-- Tests relationship definitions + +local relations = require("relations") + +describe("Schema Relations", function() + describe("constants", function() + it("should have relation type constants", function() + expect(relations.ONE_TO_ONE).toBe("one_to_one") + expect(relations.ONE_TO_MANY).toBe("one_to_many") + expect(relations.MANY_TO_MANY).toBe("many_to_many") + end) + end) + + describe("define", function() + it.each({ + { type = "one_to_one", cascade = nil, expectedCascade = false }, + { type = "one_to_many", cascade = true, expectedCascade = true }, + { type = "many_to_many", cascade = false, expectedCascade = false }, + })("should define $type relationship with cascade=$expectedCascade", function(testCase) + local from = { table = "users", field = "id" } + local to = { table = "profiles", field = "user_id" } + local options = testCase.cascade ~= nil and { cascade = testCase.cascade } or nil + + local result = relations.define(testCase.type, from, to, options) + expect(result.type).toBe(testCase.type) + expect(result.from_table).toBe("users") + expect(result.from_field).toBe("id") + expect(result.to_table).toBe("profiles") + expect(result.to_field).toBe("user_id") + expect(result.cascade).toBe(testCase.expectedCascade) + end) + end) + + describe("has_one", function() + it("should create one-to-one relationship", function() + local from = { table = "users", field = "id" } + local to = { table = "profiles", field = "user_id" } + + local result = relations.has_one(from, to) + expect(result.type).toBe("one_to_one") + expect(result.from_table).toBe("users") + expect(result.to_table).toBe("profiles") + end) + end) + + describe("has_many", function() + it("should create one-to-many relationship", function() + local from = { table = "users", field = "id" } + local to = { table = "posts", field = "author_id" } + + local result = relations.has_many(from, to) + expect(result.type).toBe("one_to_many") + expect(result.from_table).toBe("users") + expect(result.to_table).toBe("posts") + end) + end) + + describe("belongs_to_many", function() + it("should create many-to-many relationship with pivot", function() + local from = { table = "users", field = "id" } + local to = { table = "roles", field = "id" } + + local result = relations.belongs_to_many(from, to, "user_roles") + expect(result.type).toBe("many_to_many") + expect(result.pivot_table).toBe("user_roles") + end) + end) +end) diff --git a/packages/schema_editor/seed/scripts/tests/tables.test.lua b/packages/schema_editor/seed/scripts/tests/tables.test.lua new file mode 100644 index 000000000..30e420014 --- /dev/null +++ b/packages/schema_editor/seed/scripts/tests/tables.test.lua @@ -0,0 +1,61 @@ +-- Tables tests for schema_editor package +-- Tests table CRUD actions + +local tables = require("tables") + +describe("Schema Tables", function() + describe("create", function() + it.each({ + { name = "users", fields = nil, expectedFields = 0, desc = "without fields" }, + { name = "posts", fields = {}, expectedFields = 0, desc = "with empty fields" }, + })("should create table $desc", function(testCase) + local result = tables.create(testCase.name, testCase.fields) + expect(result.action).toBe("create_table") + expect(result.name).toBe(testCase.name) + expect(#result.fields).toBe(testCase.expectedFields) + end) + + it("should create table with fields", function() + local fields = { + { type = "string", name = "email" }, + { type = "number", name = "age" } + } + local result = tables.create("users", fields) + expect(result.action).toBe("create_table") + expect(#result.fields).toBe(2) + expect(result.fields[1].name).toBe("email") + end) + end) + + describe("render", function() + it("should render table editor component", function() + local table_def = { + name = "products", + fields = { { type = "string", name = "title" } } + } + local result = tables.render(table_def) + expect(result.type).toBe("table_editor") + expect(result.props.name).toBe("products") + expect(#result.props.fields).toBe(1) + end) + end) + + describe("add_field", function() + it("should create add field action", function() + local field = { type = "string", name = "description" } + local result = tables.add_field("products", field) + expect(result.action).toBe("add_field") + expect(result.table).toBe("products") + expect(result.field.name).toBe("description") + end) + end) + + describe("remove_field", function() + it("should create remove field action", function() + local result = tables.remove_field("products", "description") + expect(result.action).toBe("remove_field") + expect(result.table).toBe("products") + expect(result.field).toBe("description") + end) + end) +end)