core.lua 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. local datafile = require "datafile"
  2. local dir = require "pl.dir"
  3. local path = require "pl.path"
  4. local store = require "volksdata.store"
  5. local term = require "volksdata.term"
  6. local nsm = require "volksdata.namespace"
  7. -- Read only module properties.
  8. local PROTECTED = {
  9. store = true,
  10. reset_store = true,
  11. }
  12. local config_path = os.getenv("PKAR_CONFIG_DIR") or
  13. path.dirname(datafile.path("config/app.lua"))
  14. print ("Using config at:", config_path)
  15. local config = dofile(path.join(config_path, "app.lua"))
  16. local store_id = "file://" .. (os.getenv("PKAR_BASE") or config.fs.dres_path)
  17. -- Fill namespace map from config.
  18. for pfx, ns in pairs(config.namespace) do nsm.add(pfx, ns) end
  19. local M = {
  20. -- Project root path.
  21. config_path = config_path,
  22. config = config,
  23. store_id = store_id,
  24. --Logger config.
  25. logger = require "sllog":init{
  26. {"err", "%T PKAR %-5L ", "%n", io.stderr},
  27. {"warn", "%T PKAR %-5L ", "%n", io.stderr},
  28. {"info", "%T PKAR %-5L ", "%n", io.stderr},
  29. {"debug", "%T PKAR %-5L%f (%S) ", "%n", io.stderr},
  30. timefn=(require "socket" or {}).gettime,
  31. report="debug",
  32. hookrequire=false,
  33. level="debug",
  34. },
  35. -- Commonly used terms.
  36. RDF_TYPE = term.new_iriref(term.RDF_TYPE),
  37. -- Methods.
  38. -- Escape strings for use in gsub patterns.
  39. escape_ptn = function(src)
  40. return src:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0")
  41. end,
  42. }
  43. --[[
  44. Generate pairtree directory and file path from an ID string and prefix.
  45. The directory is created if not existing.
  46. The ID string can include the `par:` namespace prefix or the fully qualified
  47. namespace.
  48. ext is optional, and is appended to the raw path.
  49. if no_create is not nil or false, the directory will not be checked for
  50. existence or created. This is normally set for web paths.
  51. return: full file path, with the optional extension if provided.
  52. --]]
  53. M.gen_pairtree = function (pfx, id_str, ext, no_create)
  54. local bare_id = id_str:gsub(nsm.get_ns("par"), ""):gsub("^par:", "")
  55. local res_dir = path.join(pfx, bare_id:sub(1,2), bare_id:sub(3,4))
  56. local created, err
  57. if (path.isdir(res_dir)) or no_create then created = false
  58. else
  59. created, err = dir.makepath(res_dir)
  60. if not created then error(err) end
  61. end
  62. local fpath
  63. if (res_dir) then fpath = path.join(res_dir, bare_id .. (ext or "")) end
  64. return fpath, created
  65. end
  66. -- No more assignments to the module afte here.
  67. local mt = {
  68. __index = function(t, k)
  69. if (k == "store") then
  70. if not rawget(t, "_store") then
  71. rawset(t, "_store", store.new(store.MDB, store_id)) end
  72. return rawget(t, "_store")
  73. -- WIPE ALL DATA from the store and returns the new empty store handle.
  74. elseif (k == "reset_store") then
  75. rawset(t, "_store", store.new(store.MDB, store_id, true))
  76. return rawget(t, "_store")
  77. end
  78. end,
  79. __newindex = function () return nil, "Module is read only." end
  80. }
  81. setmetatable (M, mt)
  82. math.randomseed(M.config.id.seed or os.time())
  83. return M