From 048edfa86f33fdcf4b12851c272ebc82d9f39b69 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 7 Dec 2023 18:24:14 +1100 Subject: [PATCH] feat(require): add load/loadjson functions --- imports/require/shared.lua | 118 ++++++++++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 21 deletions(-) diff --git a/imports/require/shared.lua b/imports/require/shared.lua index 7b3f89a..7d25ecf 100644 --- a/imports/require/shared.lua +++ b/imports/require/shared.lua @@ -11,6 +11,102 @@ package = { local _require = require +---@param modpath string +---@param modname? string +---@return string, string? +local function getModuleInfo(modpath, modname) + local resourceSrc + + if not modpath:find('^@') then + local idx = 1 + + while true do + local di = debug.getinfo(idx, 'S') + + if di then + if not di.short_src:find('^@ox_lib/imports/require') and not di.short_src:find('^%[C%]') and not di.short_src:find('^citizen') and di.short_src ~= '?' then + resourceSrc = di.short_src:gsub('^@(.-)/.+', '%1') + break + end + else + resourceSrc = cache.resource + break + end + + idx += 1 + end + + if modname and resourceSrc ~= cache.resource then + modname = ('@%s.%s'):format(resourceSrc, modname) + end + end + + return resourceSrc, modname +end + +---@param filePath string +---@param env? table +---@return any +---Loads and runs a Lua file at the given path. Unlike require, the chunk is not cached for future use. +function lib.load(filePath, env) + local resourceSrc + local modpath = filePath:gsub('%.', '/') + + if not modpath:find('^@') then + resourceSrc = getModuleInfo(modpath) + end + + if not resourceSrc then + resourceSrc = modpath:gsub('^@(.-)/.+', '%1') + modpath = modpath:sub(#resourceSrc + 3) + end + + for path in package.path:gmatch('[^;]+') do + local scriptPath = path:gsub('?', modpath):gsub('%.+%/+', '') + local resourceFile = LoadResourceFile(resourceSrc, scriptPath) + + if resourceFile then + filePath = ('@@%s/%s'):format(resourceSrc, filePath) + + local chunk, err = load(resourceFile, filePath, 't', env or _ENV) + + if not chunk or err then + error(err or 'an unknown error occurred', 2) + end + + return chunk() + end + end + + error(('cannot load file at path %s'):format(filePath)) +end + +---@param filePath string +---@return table +---Loads and decodes a json file at the given path. +function lib.loadJson(filePath) + local resourceSrc + local modpath = filePath:gsub('%.', '/') + + if not modpath:find('^@') then + resourceSrc = getModuleInfo(modpath) + end + + if not resourceSrc then + resourceSrc = modpath:gsub('^@(.-)/.+', '%1') + modpath = modpath:sub(#resourceSrc + 3) + end + + local scriptPath = ('%s.json'):format(modpath) + local resourceFile = LoadResourceFile(resourceSrc, scriptPath) + + if resourceFile then + return json.decode(resourceFile) + end + + error(('cannot load json file at path %s'):format(filePath)) +end + ---Loads the given module inside the current resource, returning any values returned by the file or `true` when `nil`. ---@param modname string ---@return unknown? @@ -32,27 +128,7 @@ function lib.require(modname) local resourceSrc if not modpath:find('^@') then - local idx = 1 - - while true do - local di = debug.getinfo(idx, 'S') - - if di then - if not di.short_src:find('^@ox_lib/imports/require') and not di.short_src:find('^%[C%]') and not di.short_src:find('^citizen') and di.short_src ~= '?' then - resourceSrc = di.short_src:gsub('^@(.-)/.+', '%1') - break - end - else - resourceSrc = cache.resource - break - end - - idx += 1 - end - - if resourceSrc ~= cache.resource then - modname = ('@%s.%s'):format(resourceSrc, modname) - end + resourceSrc, modname = getModuleInfo(modpath, modname) --[[@as string]] end if not module then