-- search.lua -- Direct store query: full-text search across ADL-managed blog_posts table. -- Route: POST /api/v1/lua/blog/search body: { "q": "search term" } kalos.action("lua.blog.search", function(req) local q = (req.data and req.data.q) or "" if type(q) ~= "string" or #q < 2 then return { code = 400, error_code = "BAD_REQUEST", error_message = "Query 'q' must be a string of at least 2 characters" } end -- pcall the store lookup — kalos.store("app") throws if the store -- is not registered with core (ADL opens app.db internally but does -- not yet call core_->register_store("app")). local ok_s, s = pcall(kalos.store, "app") if not ok_s or not s then return { code = 503, error_code = "STORE_UNAVAILABLE", error_message = "app store not available for direct queries" } end local like = "%" .. q:lower() .. "%" local rows = {} local ok, err = pcall(function() rows = s:query( [[SELECT "id", "title", "excerpt", "status", "authorName", "publishedAt" FROM blog_posts WHERE "deletedAt" IS NULL AND (LOWER("title") LIKE ? OR LOWER("body") LIKE ? OR LOWER("excerpt") LIKE ?) ORDER BY CASE WHEN "status" = 'published' THEN 0 ELSE 1 END, "updatedAt" DESC LIMIT 20]], {like, like, like} ) end) if not ok then return { code = 500, error_code = "STORE_ERROR", error_message = tostring(err) } end return { code = 200, data = { query = q, count = #rows, results = rows } } end)