mirror of
https://github.com/lazuscripts/locator.git
synced 2024-11-19 10:54:24 +00:00
121 lines
3.8 KiB
Plaintext
121 lines
3.8 KiB
Plaintext
config = require "locator_config" -- TODO combine w values from Lapis's config, those overwriting these (this will be a legacy option)
|
|
|
|
import insert, sort from table
|
|
|
|
-- require, but only errors when a module errors during loading
|
|
check_require = (path) ->
|
|
ok, value = pcall -> require path
|
|
if ok or ("string" == type(value) and 1 == value\find "module '#{path}' not found")
|
|
return ok, value
|
|
else
|
|
error value
|
|
|
|
-- locates and returns a module
|
|
-- if a path is specified, it will be checked before other paths
|
|
-- checks the project root, then each path specified in locator_config
|
|
locate = (name, path) ->
|
|
print "locate ->"
|
|
if path
|
|
print " try '#{path}.#{name}'"
|
|
ok, value = pcall -> check_require "#{path}.#{name}"
|
|
return value if ok
|
|
|
|
print " try '#{name}'"
|
|
ok, value = pcall -> check_require name
|
|
return value if ok
|
|
|
|
for item in *config
|
|
if path
|
|
print " try '#{item.path}.#{path}.#{name}'"
|
|
ok, value = pcall -> check_require "#{item.path}.#{path}.#{name}"
|
|
else
|
|
print " try '#{item.path}.#{name}'"
|
|
ok, value = pcall -> check_require "#{item.path}.#{name}"
|
|
return value if ok
|
|
|
|
if path
|
|
error "locator could not find '#{path}.#{name}'"
|
|
else
|
|
error "locator could not find '#{name}'"
|
|
|
|
-- works like Lapis's autoload, but
|
|
-- includes trying sub-application paths & can be called to access a value
|
|
autoload = (path, tab={}) ->
|
|
return setmetatable tab, {
|
|
__call: (t, name) ->
|
|
t[name] = locate name, path
|
|
return t[name]
|
|
__index: (t, name) ->
|
|
t[name] = locate name, path
|
|
return t[name]
|
|
}
|
|
|
|
-- pass your migrations, it returns them + all sub-application migrations
|
|
-- (legacy) see example config for how to specify to not include early migrations
|
|
make_migrations = (app_migrations={}) ->
|
|
for item in *config
|
|
ok, migrations = pcall -> check_require "#{item.path}.migrations"
|
|
if ok
|
|
sorted = {}
|
|
for m in pairs migrations
|
|
insert sorted, m
|
|
sort sorted
|
|
for i in *sorted
|
|
-- only allow migrations after specified config value, or if no 'after' is specified
|
|
if (item.migrations and ((item.migrations.after and i > item.migrations.after) or not item.migrations.after)) or not item.migrations
|
|
-- if your migrations and theirs share a value, combine them
|
|
if app_fn = app_migrations[i]
|
|
app_migrations[i] = (...) ->
|
|
app_fn(...)
|
|
migrations[i](...)
|
|
-- else just add them
|
|
else
|
|
app_migrations[i] = migrations[i]
|
|
|
|
return app_migrations
|
|
|
|
-- sub-applications can define custom functions in a `locator_config` file in
|
|
-- their root directory. These functions are aggregated by name and called in
|
|
-- the order defined by the paths in the root locator_config (with the root
|
|
-- being called first)
|
|
registry = setmetatable {}, {
|
|
__index: (t, name) ->
|
|
registered_functions = {}
|
|
|
|
if config[name]
|
|
insert registered_functions, config[name]
|
|
|
|
for item in *config
|
|
ok, register = pcall -> check_require "#{item.path}.locator_config"
|
|
if ok and register[name]
|
|
insert registered_functions, register[name]
|
|
|
|
if #registered_functions > 0
|
|
t[name] = (...) ->
|
|
for i=1, #registered_functions-1
|
|
registered_functions[i](...)
|
|
return registered_functions[#registered_functions](...)
|
|
else
|
|
t[name] = ->
|
|
|
|
return t[name]
|
|
}
|
|
|
|
-- public interface:
|
|
-- functions: autoload, make_migrations
|
|
-- tables: locate (locator alias), registry
|
|
return setmetatable {
|
|
:locate, :autoload, :make_migrations, :registry
|
|
}, {
|
|
__call: (t, here="") ->
|
|
if "init" == here\sub -4
|
|
here = here\sub 1, -6
|
|
unless here\len! > 0
|
|
here = ""
|
|
return autoload here
|
|
|
|
__index: (t, name) ->
|
|
t[name] = autoload name
|
|
return t[name]
|
|
}
|