No Description
Paul Liverman III e9d8481f88 Merge commit '9ef588eb0e' as 'locator' 4 years ago
example Merge commit '9ef588eb0e' as 'locator' 4 years ago
.gitignore Merge commit '9ef588eb0e' as 'locator' 4 years ago
LICENSE Merge commit '9ef588eb0e' as 'locator' 4 years ago Merge commit '9ef588eb0e' as 'locator' 4 years ago
add.lua Merge commit '9ef588eb0e' as 'locator' 4 years ago
add.moon Merge commit '9ef588eb0e' as 'locator' 4 years ago
init.moon Merge commit '9ef588eb0e' as 'locator' 4 years ago
pull.lua Merge commit '9ef588eb0e' as 'locator' 4 years ago
pull.moon Merge commit '9ef588eb0e' as 'locator' 4 years ago


A service module locator for use with Lapis. (Which doesn’t use anythng Lapis-specific, so you could use it elsewhere.)


  1. subtree this project into the root of your project.
  2. echo 'return require((...) .. ".init")' > locator.lua (and make sure it is committed!)
  3. Make locator_config.moon using the configuration format specified below.
  4. echo 'return require("locator").models' > models.moon (to replace the models autoloader provided with Lapis with our autoloader)


  1. autoload: A function to allow automatically loading modules when accessing a table.
  2. Implicit autoloaders: The module itself is an autoloader, and can be called to create a specialized autoloader that checks directories local to where your code is before other paths.
  3. make_migrations: A function to make integrating migrations tables from multiple Lapis projects into one to streamline applying migrations.

autoload function

The core functionality is based on the autoload function, which returns a table with __call and __index metamethods, allowing things like:

locator = require "locator"

-- the module itself is an autoloader, so you can grab anything in a
-- sub-directory like so:
import Users, Posts from locator.models -- looks in 'models' directory first

-- you can also use it (locator.models) as a function to require from models
Model = locator.models "Model" -- will look for 'models.Model' (& config paths)

You can create autoloaders yourself: models = locator.autoload "models"

Implicit autoloaders

In sub-applications, make requiring things easier by acting like everything is in your repository’s root:

-- returns an autoloader that will try to require from wherever your
--  sub-application is installed before other paths
locate = require("locator")(...)

util = locate "util" -- will grab *our* utility functions

Grab a table of all views: views = locator.views (will create an autoloader when you try to access it)

make_migrations function

In your migrations, do something like this:

import make_migrations from require "locator"
import create_table, types from require "lapis.db.schema"

return make_migrations {
  [1518418142]: =>
    create_table "articles", {
      {"id", types.serial primary_key: true}
      {"title", types.text unique: true}
      {"content", types.text}

Whatever migrations you have defined will be combined with migrations specified in sub-applications added to locator_config, subject to conditions in the config file.


Example configuration:

    path: "applications.users" -- there is a sub-application at this location
    migrations: {after: 1518414112} -- don't run this migration or any before it
    path: "utility" -- another sub-application is here

The only required value per item in the configuration is path, formatted with periods as a directory-separator. Currently, the only point of specifying a migrations table is to specify a migration ID to ignore it and every migration before it within that sub-application.

Without the configuration file, locator will crash with an error, and without a path specified, locator doesn’t know where else to look for files to require, so it is very essential.