API scripts
A script with @api on its first line is the public interface of the scripts under it: it returns what it returns, and only the types its export lines name leave it.
@api on line 1, then its export linesexport lines nameWhat an ApiScript is
@api | line 1, alone |
export Purse | one per line, at the top level: a type of its types line, or of a class or module it uses |
- It works like a plain module script; the scripts under it are its insides.
- A script that uses it sees exactly the exported types.
- The
@apiline alone makes it one (shot write,shot editor the window). - The scripts under it stay reachable:
use root.Bank.Pursestill works.
The example
shot new Wallet.ssp
shot write Bank.shot --project Wallet.ssp the ApiScript, its text on stdin
shot write Bank/Types.shot --project Wallet.ssp the types it sees, under it
shot write Bank/Purse.shot --project Wallet.ssp the class Purse, under it
shot write Main.shot --project Wallet.ssp the program, which uses itshot tree --project Wallet.ssp:
Wallet.ssp
./ (the project)
Bank.shot
Purse.shot
Types.shot
Main.shotBank.shot:
@api
types script.Types
use script.Purse
export Purse
export Coins
export Source
return { Purse = Purse }Bank/Types.shot:
doc { A number of coins }
public type Coins = number
doc { Where coins came from }
public type Source = "Prize" | "Sale"
internal type Entry = { Amount : Coins, From : Source }Bank/Purse.shot:
types script.Parent.Types
doc { One person's coins }
class Purse = {
public Owner : string
public Balance : Coins
internal History : { Entry }
constructor new(owner : string)
local self : Purse = init()
self.Owner = owner
self.Balance = 0
self.History = {}
return self
end
public Add(amount : Coins, from : Source)
self.Balance += amount
table.insert(self.History, { Amount = amount, From = from })
end
}types script.Typesreads the Types.shot under it; any Types file it can reach works.export Purseexports the used class's type;export Coinsandexport Source, two of its types line.- Entry stays inside.
What a script that uses it sees
Main.shot:
use Bank
local purse : Bank.Purse = Bank.Purse.new("Ada")
local prize : Bank.Coins = 50
purse:Add(prize, "Prize")
print(purse.Owner .. " has " .. purse.Balance .. " coins")It checks with 0 errors; shot run Wallet.ssp prints Ada has 50 coins.
Bank.Purseis the class (the return) and a type;Bank.CoinsandBank.Sourceare types.- Any other type is an error naming the line to add.
local last : Bank.Entry? = nilas line 7:
Wallet.ssp/Main.shot:7:14 TypeError: Unknown type 'Bank.Entry' (Bank exports no type Entry: add export Entry to Bank.shot)The read tools
shot map, shot api and shot outline show an ApiScript's exports and return first. shot map --project Wallet.ssp:
/
Bank.shot apiscript exports Purse, Coins, Source; returns { Purse = Purse }
Main.shot program
Bank/
Purse.shot class Purse One person's coins
Types.shot types public Coins; public Source; internal Entryshot api --project Wallet.ssp opens with
./
apiscript Bank exports Purse, Coins, Source; returns { Purse = Purse }shot outline Bank --project Wallet.ssp:
apiscript Bank.shot
exports Purse, Coins, Source; returns { Purse = Purse }A module of its own
It may declare one module, named as the file, and returns it; a class, func or interface goes in a script under it.
Prizes.shot, beside Bank.shot:
@api
types script.Types
export Prize
doc { Hands out the prizes }
module Prizes = {
function Name(prize : Prize) : string
return "the " .. string.lower(prize) .. " prize"
end
}Prizes/Types.shot:
doc { A prize's size }
public type Prize = "Small" | "Big"
internal type Odds = numberAfter use Prizes, this prints the big prize; Prizes.Odds is unknown, as Bank.Entry is:
local big : Prizes.Prize = "Big"
print(Prizes.Name(big))shot map:
Prizes.shot apiscript module Prizes exports Prize; returns module Prizes Hands out the prizesshot api adds the module's members:
apiscript Prizes exports Prize; returns module Prizes
module Prizes
Name(prize : Prize) : stringAs a project's export
An ApiScript that declares its module can be a project's export: other projects see that module and its exported types only (Externals). With export Prizes in Wallet's header, Shop.ssp's Main.shot
use external "Wallet.ssp"
local big : Prizes.Prize = "Big"
print(Prizes.Name(big))prints the big prize. Shop's header records:
external "Wallet.ssp" as Wallet interface e99c4d5b0152
.Name(prize : Prize) -> string
apiscript Prizes exports Prize; returns module Prizes
module Prizes
type Prize = "Small" | "Big"One that returns a table, like Bank, is a script to other projects. With export Bank:
Shop.ssp/Main.shot:1 "Wallet.ssp" exports the script Bank, and a script can't be used from another project: only a module, a class or a func canWhat it builds to
A plain Luau module (Compiled):
- each export line becomes an
export typeline in its place, generics included:export PileforPile<T>writesexport type Pile<T> = Types.Pile<T>; - every other type of its types line stays local;
- the return is its own.
Bank.shot:
--!strict
local Types = require(script.Types)
type Entry = Types.Entry
type PurseClass = Types.PurseClass
local Purse = require(script.Purse)
export type Purse = Types.Purse
export type Coins = Types.Coins
export type Source = Types.Source
return { Purse = Purse }Mistakes and their errors
Wallet.ssp/Bank.shot:8 | export Sorce names no type this script sees (did you mean Source?) |
Wallet.ssp/Bank.shot:9 | export Coins is here twice (first at line 7) |
Without @api (Sales.shot: use Bank, then export Purse):
Wallet.ssp/Sales.shot:3 export Purse works only in an ApiScript: put @api on this file's first line to make it oneIn a class, module, func or Types file:
Wallet.ssp/Bank/Purse.shot:3 export Coins works only in an ApiScript (a script whose first line is @api); this file's public types leave it already, so remove the lineA class in an ApiScript (Market.shot):
Wallet.ssp/Market.shot:4 an ApiScript declares no class (a module or nothing): put class Market in a script under it, then use script.Market and export Market@api anywhere but alone on the first line:
Wallet.ssp/Bonus.shot:2 | @api goes on the first line of the file |
Wallet.ssp/Bonus.shot:1 | @api stands alone on the first line of the file |
