Scripts loading Scripts Dynamically in Lua
On the first line, Card = {} should be local Card = {}, otherwise Card becomes a global, breaking encapsulation. You might want to consider using strict.lua or another method of "locking" the global table to prevent mistakes like this.

Having Card double as the metatable for card instances is pretty unusual. It will work, but now Card and each of its instances are polluted with an __index property, and this could be avoided simply by writing setmetatable({}, { __index = Card }) instead of setmetatable({}, Card), which is probably what people would expect to see anyway.

You declare the function as Card:new; it has an implicit self argument because of the colon. But you never use that argument; instead, you shadow it with a local variable named self. You probably wanted to do something like local instance = setmetatable({}, self), although as mentioned it would probably be better not to have Card double as the metatable for instances, so instead you could use local instance = setmetatable({}, { __index = self }).

local Card = {}

function Card:new(cardSuit, cardType, cardId)
    local instance = setmetatable({}, { __index = self })

    instance.id = cardId
    instance.type = cardType

    -- ...

    return instance
end

return Card


The same things apply to your second block of code.