Skip to content

Commit fc09116

Browse files
authored
Merge pull request #4 from metrik-tech/feature/update-project-structure
feature/update project structure: Implement support for Metrik Client
2 parents af65f34 + ccda741 commit fc09116

24 files changed

+398
-154
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
/node_modules
22
/out
33
/include
4-
/packages
4+
/Packages
55
*.tsbuildinfo
66

7+
*/Network/*
8+
79
*.rbxm
810
*.rbxl
911

Src/Client.lua

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
--[[
2+
Metrik SDK - https://github.com/metrik-tech/sdk
3+
]]
4+
5+
local Runtime = require(script.Parent.Packages.Runtime)
6+
local Promise = require(script.Parent.Packages.Promise)
7+
local Console = require(script.Parent.Packages.Console)
8+
9+
local Error = require(script.Parent.Enums.Error)
10+
11+
local ErrorFormats = require(script.Parent.Data.ErrorFormats)
12+
13+
local ON_INIT_LIFECYCLE_NAME = "OnInit"
14+
local ON_START_LIFECYCLE_NAME = "OnStart"
15+
16+
--[=[
17+
@class MetrikSDK.Client
18+
19+
The base class developers will be interacting with. *(TO-DO: add a descriptive class description!)*
20+
]=]
21+
local MetrikSDK = {}
22+
23+
MetrikSDK.Public = {}
24+
MetrikSDK.Private = {}
25+
26+
MetrikSDK.Public.Private = MetrikSDK.Private
27+
MetrikSDK.Private.Public = MetrikSDK.Public
28+
29+
MetrikSDK.Private.Reporter = Console.new("MetrikSDK-Client")
30+
31+
function MetrikSDK.Private.FromError(_: MetrikPrivateAPI, errorEnum: string, ...: string)
32+
return string.format(ErrorFormats[errorEnum], ...)
33+
end
34+
35+
--[=[
36+
Start the Metrik SDK, once this function has been called, internal Metrik Services and Controllers should come online and start to respond and
37+
handle Metrik backend calls made to the current Roblox server.
38+
39+
:::warning
40+
Please ensure that any pre-init variables are set before calling this function, otherwise Metrik will have issues attempting to authenticate
41+
the current SDK!
42+
:::
43+
44+
@method InitializeAsync
45+
@within MetrikSDK
46+
47+
@return Promise<()>
48+
]=]
49+
--
50+
function MetrikSDK.Public.InitializeAsync(self: MetrikPublicAPI)
51+
return Promise.new(function(resolve, reject)
52+
if self.Private.IsInitialized then
53+
return reject(self.Private:FromError(Error.AlreadyInitializedError))
54+
end
55+
56+
local runtimeClockSnapshot = os.clock()
57+
local metrikControllers = Runtime:RequireChildren(
58+
script.Parent.Controllers,
59+
function(module: ModuleScript, moduleContent: { [any]: any })
60+
self.Private.Reporter:Debug(`Loading MetrikSDK Controller module: '{module.Name}'`)
61+
62+
return moduleContent
63+
end
64+
)
65+
66+
table.sort(metrikControllers, function(serviceA, serviceB)
67+
return (serviceA.Priority or 0) > (serviceB.Priority or 0)
68+
end)
69+
70+
Runtime:CallMethodOn(metrikControllers, ON_INIT_LIFECYCLE_NAME)
71+
Runtime:CallMethodOn(metrikControllers, ON_START_LIFECYCLE_NAME)
72+
73+
self.Private.IsInitialized = true
74+
75+
self.Private.Reporter:Debug(`Loaded all MetrikSDK Controller ({os.clock() - runtimeClockSnapshot}ms)`)
76+
77+
return resolve()
78+
end)
79+
end
80+
81+
type MetrikPublicAPI = typeof(MetrikSDK.Public)
82+
type MetrikPrivateAPI = typeof(MetrikSDK.Private)
83+
84+
export type MetrikSDK = MetrikPublicAPI & { Private: nil }
85+
86+
return MetrikSDK.Public

Src/Containers/Client.client.lua

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
local Metrik = require(script.Parent.Parent)
2+
3+
Metrik.Client:InitializeAsync()
4+
5+
return task.defer(script.Parent.Destroy, script.Parent)

Src/Containers/Server.server.lua

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
require(script.Parent.Parent)
2+
3+
return task.defer(script.Parent.Destroy, script.Parent)

Src/Controllers/ExampleController.lua

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
local Console = require(script.Parent.Parent.Packages.Console)
2+
3+
local ExampleController = { }
4+
5+
ExampleController.Priority = 0
6+
ExampleController.Reporter = Console.new(`{script.Name}`)
7+
8+
function ExampleController.OnStart(self: ExampleController)
9+
self.Reporter:Debug(`Hello from '{script.Name}::OnStart'`)
10+
end
11+
12+
function ExampleController.OnInit(self: ExampleController)
13+
self.Reporter:Debug(`Hello from '{script.Name}::OnInit'`)
14+
end
15+
16+
export type ExampleController = typeof(ExampleController)
17+
18+
return ExampleController
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
local ScriptContext = game:GetService("ScriptContext")
2+
3+
local Console = require(script.Parent.Parent.Packages.Console)
4+
local Signal = require(script.Parent.Parent.Packages.Signal)
5+
6+
local Network = require(script.Parent.Parent.Network.Client)
7+
8+
local MESSAGE_REPORTER_DELAY = 60
9+
10+
local LogCaptureControllers = {}
11+
12+
LogCaptureControllers.Priority = 0
13+
LogCaptureControllers.Reporter = Console.new(`{script.Name}`)
14+
15+
LogCaptureControllers.MessageQueue = {}
16+
17+
LogCaptureControllers.MessageQueueUpdated = Signal.new()
18+
19+
function LogCaptureControllers.OnMessageError(self: LogCaptureControllers, message: string, trace: string, filePath: string)
20+
table.insert(self.MessageQueue, {
21+
["message"] = message,
22+
["script"] = filePath,
23+
["trace"] = trace,
24+
})
25+
end
26+
27+
function LogCaptureControllers.OnStart(self: LogCaptureControllers)
28+
ScriptContext.Error:Connect(function(message: string, trace: string, script: Instance)
29+
local filePath = script and script:GetFullName() or "?"
30+
31+
self:OnMessageError(message, trace, filePath)
32+
end)
33+
34+
task.spawn(function()
35+
while true do
36+
task.wait(MESSAGE_REPORTER_DELAY)
37+
38+
if #self.MessageQueue == 0 then
39+
continue
40+
end
41+
42+
Network.LogError.Fire(self.MessageQueue)
43+
44+
self.MessageQueue = {}
45+
end
46+
end)
47+
end
48+
49+
export type LogCaptureControllers = typeof(LogCaptureControllers)
50+
51+
return LogCaptureControllers

Src/Data/InterfaceTheme.lua

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
2+
3+
return {
4+
Primary = {
5+
6+
},
7+
Secondary = {
8+
Black = Color3.fromRGB(0, 0, 0),
9+
LightBlack = Color3.fromRGB(20, 20, 20),
10+
White = Color3.fromRGB(255, 255, 255),
11+
Pastel = Color3.fromRGB(236, 232, 216),
12+
},
13+
14+
HeaderFont = Font.new("rbxassetid://12187375716", Enum.FontWeight.ExtraBold, Enum.FontStyle.Normal),
15+
16+
TextFont = Font.fromName(Enum.Font.SourceSans.Name, Enum.FontWeight.Medium, Enum.FontStyle.Normal),
17+
TextFontBold = Font.fromName(Enum.Font.SourceSans.Name, Enum.FontWeight.Bold, Enum.FontStyle.Normal),
18+
TextFontExtraBold = Font.fromName(Enum.Font.SourceSans.Name, Enum.FontWeight.ExtraBold, Enum.FontStyle.Normal),
19+
TextFontItalic = Font.fromName(Enum.Font.SourceSans.Name, Enum.FontWeight.Medium, Enum.FontStyle.Italic),
20+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
local Roact = require(script.Parent.Parent.Parent.Parent.Packages.Roact)
2+
local Sift = require(script.Parent.Parent.Parent.Parent.Packages.Sift)
3+
4+
local InterfaceTheme = require(script.Parent.Parent.Data.InterfaceTheme)
5+
6+
local TextLabel = Roact.Component:extend("TextLabel")
7+
8+
TextLabel.defaultProps = {
9+
FontFace = InterfaceTheme.Primary.TextFontItalic,
10+
TextColor3 = InterfaceTheme.Secondary.White,
11+
TextScaled = true,
12+
Size = UDim2.fromScale(1, 1),
13+
BackgroundTransparency = 1,
14+
Position = UDim2.fromScale(0.5, 0.5),
15+
AnchorPoint = Vector2.new(0.5, 0.5),
16+
}
17+
18+
function TextLabel:render()
19+
local shallowProps = Sift.Dictionary.copy(self.props)
20+
21+
shallowProps[Roact.Children] = nil
22+
23+
return Roact.createElement("TextLabel", shallowProps, self.props[Roact.Children])
24+
end
25+
26+
return TextLabel
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
local Roact = require(script.Parent.Parent.Parent.Parent.Packages.Roact)
2+
3+
local TextLabel = require(script.Parent.TextLabel)
4+
5+
return function(target)
6+
local handle = Roact.mount(Roact.createElement(TextLabel), target)
7+
8+
return function()
9+
Roact.unmount(handle)
10+
end
11+
end

Src/Interface/Roact/AlertBroadcast/.gitkeep

Whitespace-only changes.

Src/Interface/Roact/ToastBroadcast/.gitkeep

Whitespace-only changes.

Src/Interface/Roact/TopbarBroadcast/.gitkeep

Whitespace-only changes.

Src/Server.lua

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
--[[
2+
Metrik SDK - https://github.com/metrik-tech/sdk
3+
]]
4+
5+
local Runtime = require(script.Parent.Packages.Runtime)
6+
local Promise = require(script.Parent.Packages.Promise)
7+
local Console = require(script.Parent.Packages.Console)
8+
9+
local Error = require(script.Parent.Enums.Error)
10+
11+
local ErrorFormats = require(script.Parent.Data.ErrorFormats)
12+
13+
local Action = require(script.Parent.API.Action)
14+
15+
local ApiService = require(script.Parent.Services.ApiService)
16+
17+
local ON_INIT_LIFECYCLE_NAME = "OnInit"
18+
local ON_START_LIFECYCLE_NAME = "OnStart"
19+
20+
--[=[
21+
@class MetrikSDK.Server
22+
23+
The base class developers will be interacting with. *(TO-DO: add a descriptive class description!)*
24+
]=]
25+
local MetrikSDK = {}
26+
27+
MetrikSDK.Public = {}
28+
MetrikSDK.Private = {}
29+
30+
MetrikSDK.Public.Private = MetrikSDK.Private
31+
MetrikSDK.Private.Public = MetrikSDK.Public
32+
33+
MetrikSDK.Private.Reporter = Console.new("MetrikSDK-Server")
34+
MetrikSDK.Private.IsInitialized = false
35+
MetrikSDK.Private.ProjectId = ""
36+
37+
--[=[
38+
@prop Action Action
39+
@within MetrikSDK.Server
40+
]=]
41+
--
42+
MetrikSDK.Public.Action = Action
43+
44+
function MetrikSDK.Private.FromError(_: MetrikPrivateAPI, errorEnum: string, ...: string)
45+
return string.format(ErrorFormats[errorEnum], ...)
46+
end
47+
48+
--[=[
49+
...
50+
51+
@method SetAuthenticationToken
52+
@within MetrikSDK.Server
53+
54+
@return ()
55+
]=]
56+
--
57+
function MetrikSDK.Public.SetAuthenticationToken(self: MetrikPublicAPI, projectId: string)
58+
self.Private.Reporter:Assert(
59+
not self.Private.IsInitialized,
60+
self.Private:FromError(Error.ExpectedCallAfterCall, "Metrik:SetAuthenticationToken", "Metrik:InitializeAsync")
61+
)
62+
63+
ApiService:SetAuthenticationToken(projectId)
64+
ApiService:SetProjectId(projectId)
65+
end
66+
67+
--[=[
68+
Start the Metrik SDK, once this function has been called, internal Metrik Services and Controllers should come online and start to respond and
69+
handle Metrik backend calls made to the current Roblox server.
70+
71+
:::warning
72+
Please ensure that any pre-init variables are set before calling this function, otherwise Metrik will have issues attempting to authenticate
73+
the current SDK!
74+
:::
75+
76+
@method InitializeAsync
77+
@within MetrikSDK.Server
78+
79+
@return Promise<()>
80+
]=]
81+
--
82+
function MetrikSDK.Public.InitializeAsync(self: MetrikPublicAPI)
83+
return Promise.new(function(resolve, reject)
84+
if self.Private.IsInitialized then
85+
return reject(self.Private:FromError(Error.AlreadyInitializedError))
86+
end
87+
88+
local runtimeClockSnapshot = os.clock()
89+
local metrikServices = Runtime:RequireChildren(
90+
script.Parent.Services,
91+
function(module: ModuleScript, moduleContent: { [any]: any })
92+
self.Private.Reporter:Debug(`Loading MetrikSDK Service module: '{module.Name}'`)
93+
94+
return moduleContent
95+
end
96+
)
97+
98+
table.sort(metrikServices, function(serviceA, serviceB)
99+
return (serviceA.Priority or 0) > (serviceB.Priority or 0)
100+
end)
101+
102+
Runtime:CallMethodOn(metrikServices, ON_INIT_LIFECYCLE_NAME)
103+
Runtime:CallMethodOn(metrikServices, ON_START_LIFECYCLE_NAME)
104+
105+
self.Private.IsInitialized = true
106+
107+
self.Private.Reporter:Debug(`Loaded all MetrikSDK Services ({os.clock() - runtimeClockSnapshot}ms)`)
108+
109+
return resolve()
110+
end)
111+
end
112+
113+
type MetrikPublicAPI = typeof(MetrikSDK.Public)
114+
type MetrikPrivateAPI = typeof(MetrikSDK.Private)
115+
116+
export type MetrikSDK = MetrikPublicAPI & { Private: nil }
117+
118+
return MetrikSDK.Public

Src/Services/ActionService.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ local ApiService = require(script.Parent.ApiService)
2222
local ActionService = {}
2323

2424
ActionService.Priority = -1
25-
ActionService.Reporter = Console.new(`🎬 {script.Name}`)
25+
ActionService.Reporter = Console.new(`{script.Name}`)
2626

2727
ActionService.Actions = {} :: { [string]: Action.Action }
2828
ActionService.InternalActionsLoaded = State.new(false)

0 commit comments

Comments
 (0)