notex.nvim/lua/notex/utils/init.lua

213 lines
No EOL
4.9 KiB
Lua

-- Core utility functions
local M = {}
-- Import submodules
local logging = require('notex.utils.logging')
local errors = require('notex.utils.errors')
local types = require('notex.utils.types')
local validation = require('notex.utils.validation')
local date_utils = require('notex.utils.date')
local cache = require('notex.utils.cache')
-- Generate unique ID
function M.generate_id()
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
return string.gsub(template, '[xy]', function(c)
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
return string.format('%x', v)
end)
end
-- Generate SHA256 hash
function M.sha256(data)
local cmd = string.format("echo '%s' | sha256sum | cut -d' ' -f1", data)
local handle = io.popen(cmd)
if not handle then
return nil
end
local result = handle:read("*a")
handle:close()
return result:gsub("%s+", "")
end
-- Deep merge tables
function M.deep_merge(target, source)
for key, value in pairs(source) do
if type(value) == 'table' and type(target[key]) == 'table' then
M.deep_merge(target[key], value)
else
target[key] = value
end
end
return target
end
-- Check if file exists
function M.file_exists(path)
local f = io.open(path, "r")
if f then
f:close()
return true
end
return false
end
-- Read file content
function M.read_file(path)
local file = io.open(path, "r")
if not file then
return nil, "Cannot open file: " .. path
end
local content = file:read("*a")
file:close()
return content
end
-- Write file content
function M.write_file(path, content)
local file = io.open(path, "w")
if not file then
return false, "Cannot write to file: " .. path
end
file:write(content)
file:close()
return true
end
-- Get file modification time
function M.get_file_mtime(path)
local handle = io.popen("stat -c %Y " .. path .. " 2>/dev/null")
if not handle then
return nil
end
local result = handle:read("*a")
handle:close()
local mtime = tonumber(result:gsub("%s+", ""))
return mtime
end
-- Validate file encoding (UTF-8 check)
function M.is_utf8(path)
local file = io.open(path, "rb")
if not file then
return false
end
local content = file:read("*a")
file:close()
-- Simple UTF-8 validation
local valid, pos = utf8.len(content)
return valid ~= nil
end
-- Format error message
function M.format_error(error_type, message, context)
local error_obj = {
error_type = error_type,
message = message,
timestamp = os.time()
}
if context then
error_obj.context = context
end
return error_obj
end
-- Forward logging functions to centralized logging
M.trace = logging.trace
M.debug = logging.debug
M.info = logging.info
M.warn = logging.warn
M.error = logging.error
M.fatal = logging.fatal
M.log = logging.log
M.timer = logging.timer
-- Forward error handling functions
M.handle_error = errors.handle_error
M.safe_execute = errors.safe_execute
M.wrap = errors.wrap
M.create_error = errors.create_error
-- Forward type utilities
M.detect_type = types.detect_type
M.convert_to_type = types.convert_to_type
M.infer_schema = types.infer_schema
-- Forward validation utilities
M.validate_value = validation.validate_value
M.validate_document_properties = validation.validate_document_properties
M.sanitize_input = validation.sanitize_input
-- Forward date utilities
M.parse_date = date_utils.parse_date
M.format_date = date_utils.format_date
M.get_relative_time = date_utils.get_relative_time
-- Forward cache utilities
M.cache_set = cache.set
M.cache_get = cache.get
M.cache_get_or_set = cache.get_or_set
M.cache_invalidate = cache.invalidate
M.cache_clear_all = cache.clear_all
M.cache_get_stats = cache.get_stats
M.cache_init = cache.init
-- Simple timer for backward compatibility
function M.simple_timer(name)
local start_time = vim.loop.hrtime()
return function()
local end_time = vim.loop.hrtime()
local elapsed_ms = (end_time - start_time) / 1e6
M.log("INFO", string.format("%s completed in %.2fms", name, elapsed_ms))
return elapsed_ms
end
end
-- Validate data types
function M.validate_type(value, expected_type)
local actual_type = type(value)
if expected_type == "number" then
return actual_type == "number"
elseif expected_type == "string" then
return actual_type == "string"
elseif expected_type == "boolean" then
return actual_type == "boolean"
elseif expected_type == "table" then
return actual_type == "table"
elseif expected_type == "function" then
return actual_type == "function"
end
return false
end
-- Escape SQL values
function M.escape_sql(value)
if type(value) == "string" then
return "'" .. value:gsub("'", "''") .. "'"
elseif type(value) == "number" then
return tostring(value)
elseif type(value) == "boolean" then
return value and "1" or "0"
elseif value == nil then
return "NULL"
else
return "'" .. tostring(value):gsub("'", "''") .. "'"
end
end
return M