-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.lua
134 lines (98 loc) · 3.4 KB
/
init.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
--!nolint LocalShadow
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Types = require(script.Utils.Types)
local requireMeta = {}
function requireMeta:__tostring(): string
return "function: require"
end
local function containsDuplicate(container: Types.Array<Instance | string>): boolean
local total = #container
for index, value in container do
for innerIndex = index + 1, total do
if value == container[innerIndex] then
return true
end
end
end
return false
end
local function maybeThrow(message: string, condition: boolean, ...: any): nil
if not condition then
return
end
local formatted = string.format(message, ...)
error(formatted)
end
local function findFirstModule(name: string, from: Instance, path: string): Instance?
local instance = from:FindFirstChild(name)
maybeThrow("cannot locate module %s in %s from import %s", not instance, name, from:GetFullName(), path)
return instance
end
local function processPath(path: Instance | string, moduleDirectory: Instance): (Instance, Types.Array<string>)
local instance, routes
local parent = moduleDirectory
local path: string = if typeof(path) == "string" then path else path:GetFullName()
local partitions = path:split("/")
local totalPartitions = #partitions
for i, partition in partitions do
if i < totalPartitions then
parent = findFirstModule(partition, parent, path)
else
routes = partition:split(".")
local head = table.remove(routes, 1)
instance = findFirstModule(head, parent, path)
end
end
return instance, routes
end
type Props = {
AllowDuplicates: boolean?,
Directory: Instance?,
}
local DEFAULT_PROPS: Props = {
AllowDuplicates = false,
Directory = ReplicatedStorage,
}
local function processParameters(args: { Instance | string | Props }): ({ Instance | string }, Props)
local props = args[#args]
if typeof(props) ~= "table" then
return args :: { Instance | string }, DEFAULT_PROPS
end
for property: string, defaultValue in DEFAULT_PROPS :: { [string]: any } do
if props[property] == nil then
props[property] = defaultValue
end
end
table.remove(args, #args)
return args :: { Instance | string }, props
end
type Require = (...Instance | string | Props) -> ...{ any } | ((...any) -> any) | nil
function requireMeta:__call(...: Instance | string | Props): ...{ any } | ((...any) -> any) | nil
local paths, props = processParameters({ ... })
local modules = {}
maybeThrow("expected 1 or more modules, got 0", #paths == 0)
maybeThrow("cannot import duplicate modules", not props.AllowDuplicates and containsDuplicate(paths))
for _, path in paths do
local routes: Types.Array<string> = {}
maybeThrow("cannot import nil", path == nil)
if typeof(path) == "string" then
path, routes = processPath(path, props.Directory)
end
local module = require(path)
for _, route in routes do
local submodule = module[route]
maybeThrow("cannot import %s from %s", submodule == nil, route, tostring(path))
module = module[route]
end
table.insert(modules, module)
end
return table.unpack(modules)
end
local function unsafeForceCast<T, O>(value: T): O
return (value :: any) :: O
end
-- for this to act like a function without being one and benefit from the custom
-- repr that __tostring provides, ive masked the type to effectively be the same
-- function type signature as __call
local newRequire: Require = unsafeForceCast(setmetatable({}, requireMeta))
return newRequire