summaryrefslogtreecommitdiff
path: root/modules.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-03-31 20:41:29 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-03-31 20:41:29 -0600
commit6621406fa8b44826477ba7cbe2ff6c5462048f8e (patch)
treee06d9dcf413839ea4a3bbd78a783b56b3ba577f6 /modules.go
parent27ff6aeccb99995880a86ee482dd90c1e5c85d85 (diff)
Very basic middleware and route matching functionality
Diffstat (limited to 'modules.go')
-rw-r--r--modules.go42
1 files changed, 39 insertions, 3 deletions
diff --git a/modules.go b/modules.go
index 4a396d4..efd5d4a 100644
--- a/modules.go
+++ b/modules.go
@@ -43,7 +43,7 @@ func GetModule(name string) (Module, error) {
// GetModules returns all modules in the given scope/namespace.
// For example, a scope of "foo" returns modules named "foo.bar",
-// "foo.lor", but not "bar", "foo.bar.lor", etc. An empty scope
+// "foo.lee", but not "bar", "foo.bar.lee", etc. An empty scope
// returns top-level modules, for example "foo" or "bar". Partial
// scopes are not matched (i.e. scope "foo.ba" does not match
// name "foo.bar").
@@ -111,9 +111,16 @@ func Modules() []string {
// value, it is converted to one so that it is unmarshaled
// into the underlying concrete type. If mod.New is nil, an
// error is returned.
-func LoadModule(mod Module, rawMsg json.RawMessage) (interface{}, error) {
+func LoadModule(name string, rawMsg json.RawMessage) (interface{}, error) {
+ modulesMu.Lock()
+ mod, ok := modules[name]
+ modulesMu.Unlock()
+ if !ok {
+ return nil, fmt.Errorf("unknown module: %s", name)
+ }
+
if mod.New == nil {
- return nil, fmt.Errorf("no constructor")
+ return nil, fmt.Errorf("module '%s' has no constructor", mod.Name)
}
val, err := mod.New()
@@ -134,6 +141,35 @@ func LoadModule(mod Module, rawMsg json.RawMessage) (interface{}, error) {
return val, nil
}
+// LoadModuleInlineName loads a module from a JSON raw message which
+// decodes to a map[string]interface{}, and where one of the keys is
+// "_module", which indicates the module name and which be found in
+// the given scope.
+//
+// This allows modules to be decoded into their concrete types and
+// used when their names cannot be the unique key in a map, such as
+// when there are multiple instances in the map or it appears in an
+// array (where there are no custom keys).
+func LoadModuleInlineName(moduleScope string, raw json.RawMessage) (interface{}, error) {
+ var tmp map[string]interface{}
+ err := json.Unmarshal(raw, &tmp)
+ if err != nil {
+ return nil, err
+ }
+
+ moduleName, ok := tmp["_module"].(string)
+ if !ok || moduleName == "" {
+ return nil, fmt.Errorf("module name not specified")
+ }
+
+ val, err := LoadModule(moduleScope+"."+moduleName, raw)
+ if err != nil {
+ return nil, fmt.Errorf("loading module '%s': %v", moduleName, err)
+ }
+
+ return val, nil
+}
+
var (
modules = make(map[string]Module)
modulesMu sync.Mutex