add documentation site with markdown rendering (M12)
This commit is contained in:
806
portal/internal/web/docs/api/lua-api.md
Normal file
806
portal/internal/web/docs/api/lua-api.md
Normal file
@@ -0,0 +1,806 @@
|
||||
# Lua API Reference
|
||||
|
||||
Complete reference for the Mosis Lua API available to apps.
|
||||
|
||||
## Global Objects
|
||||
|
||||
### document
|
||||
|
||||
The current RML document. Use to query and modify UI elements.
|
||||
|
||||
```lua
|
||||
-- Get element by ID
|
||||
local elem = document:GetElementById("my-id")
|
||||
|
||||
-- Get elements by tag
|
||||
local buttons = document:GetElementsByTagName("button")
|
||||
|
||||
-- Get elements by class
|
||||
local cards = document:GetElementsByClassName("card")
|
||||
```
|
||||
|
||||
### event
|
||||
|
||||
Available in event handler functions. Contains information about the triggering event.
|
||||
|
||||
```lua
|
||||
function handleClick(event)
|
||||
local target = event:GetCurrentElement()
|
||||
local eventType = event.type
|
||||
end
|
||||
```
|
||||
|
||||
## Document Methods
|
||||
|
||||
### GetElementById(id)
|
||||
|
||||
Returns the element with the specified ID, or `nil` if not found.
|
||||
|
||||
```lua
|
||||
local element = document:GetElementById("username-input")
|
||||
if element then
|
||||
element.inner_rml = "Found!"
|
||||
end
|
||||
```
|
||||
|
||||
### GetElementsByTagName(tag)
|
||||
|
||||
Returns a table of all elements with the specified tag name.
|
||||
|
||||
```lua
|
||||
local buttons = document:GetElementsByTagName("button")
|
||||
for i, btn in ipairs(buttons) do
|
||||
btn:SetClass("styled", true)
|
||||
end
|
||||
```
|
||||
|
||||
### GetElementsByClassName(class)
|
||||
|
||||
Returns a table of all elements with the specified class name.
|
||||
|
||||
```lua
|
||||
local items = document:GetElementsByClassName("list-item")
|
||||
```
|
||||
|
||||
### CreateElement(tag)
|
||||
|
||||
Creates a new element with the specified tag name.
|
||||
|
||||
```lua
|
||||
local div = document:CreateElement("div")
|
||||
div.inner_rml = "New element"
|
||||
parent:AppendChild(div)
|
||||
```
|
||||
|
||||
### CreateTextNode(text)
|
||||
|
||||
Creates a text node with the specified content.
|
||||
|
||||
```lua
|
||||
local text = document:CreateTextNode("Hello")
|
||||
element:AppendChild(text)
|
||||
```
|
||||
|
||||
## Element Properties
|
||||
|
||||
### inner_rml
|
||||
|
||||
Gets or sets the inner RML content of an element.
|
||||
|
||||
```lua
|
||||
-- Get content
|
||||
local content = element.inner_rml
|
||||
|
||||
-- Set content (parses RML)
|
||||
element.inner_rml = "<strong>Bold text</strong>"
|
||||
```
|
||||
|
||||
### id
|
||||
|
||||
Gets or sets the element's ID.
|
||||
|
||||
```lua
|
||||
local id = element.id
|
||||
element.id = "new-id"
|
||||
```
|
||||
|
||||
### style
|
||||
|
||||
Access to the element's inline styles.
|
||||
|
||||
```lua
|
||||
element.style.width = "100dp"
|
||||
element.style.backgroundColor = "#ff0000"
|
||||
element.style.display = "none"
|
||||
```
|
||||
|
||||
### parent_node
|
||||
|
||||
Returns the parent element, or `nil` if none.
|
||||
|
||||
```lua
|
||||
local parent = element.parent_node
|
||||
```
|
||||
|
||||
### first_child / last_child
|
||||
|
||||
Returns the first or last child element.
|
||||
|
||||
```lua
|
||||
local first = container.first_child
|
||||
local last = container.last_child
|
||||
```
|
||||
|
||||
### next_sibling / previous_sibling
|
||||
|
||||
Returns the next or previous sibling element.
|
||||
|
||||
```lua
|
||||
local next = element.next_sibling
|
||||
```
|
||||
|
||||
### child_nodes
|
||||
|
||||
Returns a table of all child elements.
|
||||
|
||||
```lua
|
||||
local children = element.child_nodes
|
||||
for i, child in ipairs(children) do
|
||||
print(child.id)
|
||||
end
|
||||
```
|
||||
|
||||
### tag_name
|
||||
|
||||
Returns the element's tag name (lowercase).
|
||||
|
||||
```lua
|
||||
local tag = element.tag_name -- "div", "button", etc.
|
||||
```
|
||||
|
||||
### offset_width / offset_height
|
||||
|
||||
Returns the rendered dimensions of the element.
|
||||
|
||||
```lua
|
||||
local width = element.offset_width
|
||||
local height = element.offset_height
|
||||
```
|
||||
|
||||
### offset_left / offset_top
|
||||
|
||||
Returns the position relative to the offset parent.
|
||||
|
||||
```lua
|
||||
local x = element.offset_left
|
||||
local y = element.offset_top
|
||||
```
|
||||
|
||||
## Element Methods
|
||||
|
||||
### GetAttribute(name)
|
||||
|
||||
Returns the value of the specified attribute.
|
||||
|
||||
```lua
|
||||
local value = input:GetAttribute("value")
|
||||
local placeholder = input:GetAttribute("placeholder")
|
||||
```
|
||||
|
||||
### SetAttribute(name, value)
|
||||
|
||||
Sets the value of the specified attribute.
|
||||
|
||||
```lua
|
||||
input:SetAttribute("placeholder", "Enter text...")
|
||||
button:SetAttribute("disabled", "disabled")
|
||||
```
|
||||
|
||||
### RemoveAttribute(name)
|
||||
|
||||
Removes the specified attribute.
|
||||
|
||||
```lua
|
||||
button:RemoveAttribute("disabled")
|
||||
```
|
||||
|
||||
### HasAttribute(name)
|
||||
|
||||
Returns `true` if the element has the specified attribute.
|
||||
|
||||
```lua
|
||||
if button:HasAttribute("disabled") then
|
||||
print("Button is disabled")
|
||||
end
|
||||
```
|
||||
|
||||
### SetClass(name, add)
|
||||
|
||||
Adds or removes a class from the element.
|
||||
|
||||
```lua
|
||||
-- Add class
|
||||
element:SetClass("active", true)
|
||||
|
||||
-- Remove class
|
||||
element:SetClass("active", false)
|
||||
```
|
||||
|
||||
### IsClassSet(name)
|
||||
|
||||
Returns `true` if the element has the specified class.
|
||||
|
||||
```lua
|
||||
if element:IsClassSet("selected") then
|
||||
print("Element is selected")
|
||||
end
|
||||
```
|
||||
|
||||
### AppendChild(element)
|
||||
|
||||
Appends a child element.
|
||||
|
||||
```lua
|
||||
local child = document:CreateElement("div")
|
||||
parent:AppendChild(child)
|
||||
```
|
||||
|
||||
### InsertBefore(element, reference)
|
||||
|
||||
Inserts an element before the reference element.
|
||||
|
||||
```lua
|
||||
parent:InsertBefore(newElement, referenceElement)
|
||||
```
|
||||
|
||||
### RemoveChild(element)
|
||||
|
||||
Removes a child element.
|
||||
|
||||
```lua
|
||||
parent:RemoveChild(childElement)
|
||||
```
|
||||
|
||||
### Focus()
|
||||
|
||||
Sets focus to the element.
|
||||
|
||||
```lua
|
||||
input:Focus()
|
||||
```
|
||||
|
||||
### Blur()
|
||||
|
||||
Removes focus from the element.
|
||||
|
||||
```lua
|
||||
input:Blur()
|
||||
```
|
||||
|
||||
### Click()
|
||||
|
||||
Simulates a click on the element.
|
||||
|
||||
```lua
|
||||
button:Click()
|
||||
```
|
||||
|
||||
### ScrollIntoView(alignToTop)
|
||||
|
||||
Scrolls the element into view.
|
||||
|
||||
```lua
|
||||
element:ScrollIntoView(true) -- align to top
|
||||
element:ScrollIntoView(false) -- align to bottom
|
||||
```
|
||||
|
||||
### AddEventListener(event, handler)
|
||||
|
||||
Adds an event listener to the element.
|
||||
|
||||
```lua
|
||||
button:AddEventListener("click", function(event)
|
||||
print("Clicked!")
|
||||
end)
|
||||
```
|
||||
|
||||
### RemoveEventListener(event, handler)
|
||||
|
||||
Removes an event listener from the element.
|
||||
|
||||
```lua
|
||||
local handler = function(event) print("Click") end
|
||||
button:AddEventListener("click", handler)
|
||||
button:RemoveEventListener("click", handler)
|
||||
```
|
||||
|
||||
## Event Object
|
||||
|
||||
### type
|
||||
|
||||
The event type string (e.g., "click", "change").
|
||||
|
||||
```lua
|
||||
if event.type == "click" then
|
||||
-- handle click
|
||||
end
|
||||
```
|
||||
|
||||
### target_element
|
||||
|
||||
The element that originally triggered the event.
|
||||
|
||||
```lua
|
||||
local target = event.target_element
|
||||
```
|
||||
|
||||
### current_element
|
||||
|
||||
The element the event handler is attached to.
|
||||
|
||||
```lua
|
||||
local current = event.current_element
|
||||
```
|
||||
|
||||
### GetCurrentElement()
|
||||
|
||||
Returns the current element (same as `current_element`).
|
||||
|
||||
```lua
|
||||
local elem = event:GetCurrentElement()
|
||||
```
|
||||
|
||||
### StopPropagation()
|
||||
|
||||
Stops the event from bubbling up to parent elements.
|
||||
|
||||
```lua
|
||||
event:StopPropagation()
|
||||
```
|
||||
|
||||
### StopImmediatePropagation()
|
||||
|
||||
Stops the event and prevents other handlers on the same element.
|
||||
|
||||
```lua
|
||||
event:StopImmediatePropagation()
|
||||
```
|
||||
|
||||
### parameters
|
||||
|
||||
Table containing event-specific parameters.
|
||||
|
||||
```lua
|
||||
-- Mouse events
|
||||
local x = event.parameters.mouse_x
|
||||
local y = event.parameters.mouse_y
|
||||
local button = event.parameters.button -- 0=left, 1=right, 2=middle
|
||||
|
||||
-- Keyboard events
|
||||
local key = event.parameters.key_identifier
|
||||
local ctrl = event.parameters.ctrl_key
|
||||
local shift = event.parameters.shift_key
|
||||
local alt = event.parameters.alt_key
|
||||
```
|
||||
|
||||
## Navigation
|
||||
|
||||
### navigateTo(screen)
|
||||
|
||||
Navigates to a screen, pushing to history.
|
||||
|
||||
```lua
|
||||
navigateTo("settings") -- loads assets/settings.rml
|
||||
navigateTo("screens/profile") -- loads assets/screens/profile.rml
|
||||
```
|
||||
|
||||
### goBack()
|
||||
|
||||
Navigates back to the previous screen.
|
||||
|
||||
```lua
|
||||
goBack()
|
||||
```
|
||||
|
||||
### goHome()
|
||||
|
||||
Navigates to the home screen, clearing history.
|
||||
|
||||
```lua
|
||||
goHome()
|
||||
```
|
||||
|
||||
### replaceTo(screen)
|
||||
|
||||
Replaces current screen without adding to history.
|
||||
|
||||
```lua
|
||||
replaceTo("login") -- no back navigation possible
|
||||
```
|
||||
|
||||
### canGoBack()
|
||||
|
||||
Returns `true` if there's a previous screen in history.
|
||||
|
||||
```lua
|
||||
if canGoBack() then
|
||||
backButton.style.display = "block"
|
||||
else
|
||||
backButton.style.display = "none"
|
||||
end
|
||||
```
|
||||
|
||||
## Timers
|
||||
|
||||
### setTimeout(callback, delay)
|
||||
|
||||
Executes callback once after delay (milliseconds). Returns timer ID.
|
||||
|
||||
```lua
|
||||
local id = setTimeout(function()
|
||||
print("Executed after 1 second")
|
||||
end, 1000)
|
||||
```
|
||||
|
||||
### clearTimeout(id)
|
||||
|
||||
Cancels a timeout.
|
||||
|
||||
```lua
|
||||
local id = setTimeout(callback, 1000)
|
||||
clearTimeout(id)
|
||||
```
|
||||
|
||||
### setInterval(callback, interval)
|
||||
|
||||
Executes callback repeatedly. Returns timer ID.
|
||||
|
||||
```lua
|
||||
local id = setInterval(function()
|
||||
updateClock()
|
||||
end, 1000)
|
||||
```
|
||||
|
||||
### clearInterval(id)
|
||||
|
||||
Cancels an interval.
|
||||
|
||||
```lua
|
||||
clearInterval(intervalId)
|
||||
```
|
||||
|
||||
## Storage
|
||||
|
||||
Persistent key-value storage. Data persists between app sessions.
|
||||
|
||||
### storage.set(key, value)
|
||||
|
||||
Stores a value. Value can be string, number, boolean, or table.
|
||||
|
||||
```lua
|
||||
storage.set("username", "alice")
|
||||
storage.set("settings", { darkMode = true, fontSize = 16 })
|
||||
storage.set("highScore", 1000)
|
||||
```
|
||||
|
||||
### storage.get(key)
|
||||
|
||||
Retrieves a stored value, or `nil` if not found.
|
||||
|
||||
```lua
|
||||
local username = storage.get("username")
|
||||
local settings = storage.get("settings")
|
||||
if settings then
|
||||
print(settings.darkMode)
|
||||
end
|
||||
```
|
||||
|
||||
### storage.remove(key)
|
||||
|
||||
Removes a stored value.
|
||||
|
||||
```lua
|
||||
storage.remove("tempData")
|
||||
```
|
||||
|
||||
### storage.clear()
|
||||
|
||||
Removes all stored values.
|
||||
|
||||
```lua
|
||||
storage.clear()
|
||||
```
|
||||
|
||||
### storage.keys()
|
||||
|
||||
Returns a table of all storage keys.
|
||||
|
||||
```lua
|
||||
local keys = storage.keys()
|
||||
for i, key in ipairs(keys) do
|
||||
print(key)
|
||||
end
|
||||
```
|
||||
|
||||
## HTTP (requires `network` permission)
|
||||
|
||||
### http.get(url, callback)
|
||||
|
||||
Makes a GET request.
|
||||
|
||||
```lua
|
||||
http.get("https://api.example.com/data", function(response)
|
||||
if response.ok then
|
||||
local data = json.decode(response.body)
|
||||
print(data.message)
|
||||
else
|
||||
print("Error: " .. response.status)
|
||||
end
|
||||
end)
|
||||
```
|
||||
|
||||
### http.post(url, options, callback)
|
||||
|
||||
Makes a POST request.
|
||||
|
||||
```lua
|
||||
http.post("https://api.example.com/submit", {
|
||||
headers = {
|
||||
["Content-Type"] = "application/json",
|
||||
["Authorization"] = "Bearer token123"
|
||||
},
|
||||
body = json.encode({ name = "test" })
|
||||
}, function(response)
|
||||
print("Status: " .. response.status)
|
||||
end)
|
||||
```
|
||||
|
||||
### http.request(options, callback)
|
||||
|
||||
Makes a custom HTTP request.
|
||||
|
||||
```lua
|
||||
http.request({
|
||||
method = "PUT",
|
||||
url = "https://api.example.com/resource/1",
|
||||
headers = { ["Content-Type"] = "application/json" },
|
||||
body = json.encode({ updated = true }),
|
||||
timeout = 5000 -- milliseconds
|
||||
}, function(response)
|
||||
print(response.status)
|
||||
end)
|
||||
```
|
||||
|
||||
### Response Object
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `ok` | boolean | `true` if status is 200-299 |
|
||||
| `status` | number | HTTP status code |
|
||||
| `statusText` | string | Status message |
|
||||
| `headers` | table | Response headers |
|
||||
| `body` | string | Response body |
|
||||
|
||||
## JSON
|
||||
|
||||
### json.encode(value)
|
||||
|
||||
Converts a Lua value to a JSON string.
|
||||
|
||||
```lua
|
||||
local str = json.encode({
|
||||
name = "Alice",
|
||||
items = {"a", "b", "c"},
|
||||
count = 3
|
||||
})
|
||||
-- '{"name":"Alice","items":["a","b","c"],"count":3}'
|
||||
```
|
||||
|
||||
### json.decode(str)
|
||||
|
||||
Parses a JSON string into a Lua value.
|
||||
|
||||
```lua
|
||||
local data = json.decode('{"name":"Alice","age":25}')
|
||||
print(data.name) -- "Alice"
|
||||
print(data.age) -- 25
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
### print(...)
|
||||
|
||||
Outputs to the debug console. Accepts multiple arguments.
|
||||
|
||||
```lua
|
||||
print("Debug message")
|
||||
print("Value:", someValue, "Count:", count)
|
||||
```
|
||||
|
||||
### console.log(...)
|
||||
|
||||
Alias for `print()`.
|
||||
|
||||
```lua
|
||||
console.log("Hello")
|
||||
```
|
||||
|
||||
### console.warn(...)
|
||||
|
||||
Logs a warning message.
|
||||
|
||||
```lua
|
||||
console.warn("Something might be wrong")
|
||||
```
|
||||
|
||||
### console.error(...)
|
||||
|
||||
Logs an error message.
|
||||
|
||||
```lua
|
||||
console.error("Something went wrong:", errorMessage)
|
||||
```
|
||||
|
||||
## Utility Functions
|
||||
|
||||
### tostring(value)
|
||||
|
||||
Converts a value to a string.
|
||||
|
||||
```lua
|
||||
local str = tostring(123) -- "123"
|
||||
```
|
||||
|
||||
### tonumber(value)
|
||||
|
||||
Converts a value to a number.
|
||||
|
||||
```lua
|
||||
local num = tonumber("123") -- 123
|
||||
local invalid = tonumber("abc") -- nil
|
||||
```
|
||||
|
||||
### type(value)
|
||||
|
||||
Returns the type of a value as a string.
|
||||
|
||||
```lua
|
||||
type("hello") -- "string"
|
||||
type(123) -- "number"
|
||||
type(true) -- "boolean"
|
||||
type({}) -- "table"
|
||||
type(nil) -- "nil"
|
||||
type(print) -- "function"
|
||||
```
|
||||
|
||||
### pairs(table)
|
||||
|
||||
Iterator for all key-value pairs.
|
||||
|
||||
```lua
|
||||
for key, value in pairs(myTable) do
|
||||
print(key, value)
|
||||
end
|
||||
```
|
||||
|
||||
### ipairs(table)
|
||||
|
||||
Iterator for array elements (integer keys starting from 1).
|
||||
|
||||
```lua
|
||||
for index, value in ipairs(myArray) do
|
||||
print(index, value)
|
||||
end
|
||||
```
|
||||
|
||||
### pcall(func, ...)
|
||||
|
||||
Calls a function in protected mode (catches errors).
|
||||
|
||||
```lua
|
||||
local success, result = pcall(function()
|
||||
return json.decode(maybeInvalidJson)
|
||||
end)
|
||||
|
||||
if success then
|
||||
print("Parsed:", result)
|
||||
else
|
||||
print("Error:", result)
|
||||
end
|
||||
```
|
||||
|
||||
## Standard Libraries
|
||||
|
||||
### string
|
||||
|
||||
```lua
|
||||
string.len(s) -- length
|
||||
string.upper(s) -- uppercase
|
||||
string.lower(s) -- lowercase
|
||||
string.sub(s, i, j) -- substring
|
||||
string.find(s, pattern) -- find pattern
|
||||
string.gsub(s, pattern, repl) -- replace
|
||||
string.match(s, pattern) -- match pattern
|
||||
string.format(fmt, ...) -- format string
|
||||
string.byte(s, i) -- character code
|
||||
string.char(...) -- character from code
|
||||
string.rep(s, n) -- repeat string
|
||||
string.reverse(s) -- reverse string
|
||||
string.split(s, sep) -- split by separator (extension)
|
||||
string.trim(s) -- trim whitespace (extension)
|
||||
```
|
||||
|
||||
### math
|
||||
|
||||
```lua
|
||||
math.abs(x) -- absolute value
|
||||
math.ceil(x) -- round up
|
||||
math.floor(x) -- round down
|
||||
math.round(x) -- round to nearest (extension)
|
||||
math.max(...) -- maximum
|
||||
math.min(...) -- minimum
|
||||
math.sqrt(x) -- square root
|
||||
math.pow(x, y) -- power
|
||||
math.exp(x) -- e^x
|
||||
math.log(x) -- natural log
|
||||
math.sin(x) -- sine
|
||||
math.cos(x) -- cosine
|
||||
math.tan(x) -- tangent
|
||||
math.asin(x) -- arc sine
|
||||
math.acos(x) -- arc cosine
|
||||
math.atan(x) -- arc tangent
|
||||
math.atan2(y, x) -- arc tangent of y/x
|
||||
math.deg(x) -- radians to degrees
|
||||
math.rad(x) -- degrees to radians
|
||||
math.random() -- random 0-1
|
||||
math.random(n) -- random 1-n
|
||||
math.random(m, n) -- random m-n
|
||||
math.randomseed(x) -- set random seed
|
||||
math.pi -- 3.14159...
|
||||
math.huge -- infinity
|
||||
```
|
||||
|
||||
### table
|
||||
|
||||
```lua
|
||||
table.insert(t, value) -- append
|
||||
table.insert(t, pos, value) -- insert at position
|
||||
table.remove(t) -- remove last
|
||||
table.remove(t, pos) -- remove at position
|
||||
table.sort(t) -- sort ascending
|
||||
table.sort(t, comp) -- sort with comparator
|
||||
table.concat(t, sep) -- join to string
|
||||
table.unpack(t) -- unpack to values (extension)
|
||||
table.pack(...) -- pack values to table (extension)
|
||||
```
|
||||
|
||||
### os
|
||||
|
||||
```lua
|
||||
os.time() -- current timestamp
|
||||
os.time(t) -- timestamp from table
|
||||
os.date() -- current date string
|
||||
os.date(format) -- formatted date
|
||||
os.date(format, t) -- formatted date for timestamp
|
||||
os.date("*t") -- date as table
|
||||
os.difftime(t2, t1) -- time difference
|
||||
os.clock() -- CPU time used
|
||||
```
|
||||
|
||||
Date format codes:
|
||||
- `%Y` - 4-digit year
|
||||
- `%m` - month (01-12)
|
||||
- `%d` - day (01-31)
|
||||
- `%H` - hour (00-23)
|
||||
- `%M` - minute (00-59)
|
||||
- `%S` - second (00-59)
|
||||
- `%a` - abbreviated weekday
|
||||
- `%A` - full weekday
|
||||
- `%b` - abbreviated month
|
||||
- `%B` - full month
|
||||
|
||||
## See Also
|
||||
|
||||
- [Lua Scripting Guide](../guides/lua-scripting.md) - Tutorials and examples
|
||||
- [Permissions Guide](../guides/permissions.md) - Permission system
|
||||
- [UI Design Guide](../guides/ui-design.md) - RML/RCSS reference
|
||||
341
portal/internal/web/docs/api/manifest.md
Normal file
341
portal/internal/web/docs/api/manifest.md
Normal file
@@ -0,0 +1,341 @@
|
||||
# Manifest Reference
|
||||
|
||||
Every Mosis app requires a `manifest.json` file in the root of the package. This file describes your app and its requirements.
|
||||
|
||||
## Complete Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "com.example.myapp",
|
||||
"name": "My App",
|
||||
"version": "1.0.0",
|
||||
"version_code": 1,
|
||||
"entry": "assets/main.rml",
|
||||
"permissions": [],
|
||||
"min_mosis_version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Developer Name",
|
||||
"email": "dev@example.com",
|
||||
"url": "https://example.com"
|
||||
},
|
||||
"icons": {
|
||||
"32": "icons/icon-32.png",
|
||||
"64": "icons/icon-64.png",
|
||||
"128": "icons/icon-128.png"
|
||||
},
|
||||
"description": "A short description of your app",
|
||||
"category": "utilities",
|
||||
"screenshots": [
|
||||
"screenshots/1.png",
|
||||
"screenshots/2.png"
|
||||
],
|
||||
"locales": {
|
||||
"default": "en",
|
||||
"supported": ["en", "es", "fr"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Required Fields
|
||||
|
||||
### id
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
Unique package identifier in reverse domain notation. Must match the ID registered in the developer portal.
|
||||
|
||||
```json
|
||||
"id": "com.yourcompany.appname"
|
||||
```
|
||||
|
||||
Rules:
|
||||
- Lowercase letters, numbers, and periods only
|
||||
- Must have at least two segments (e.g., `com.app`)
|
||||
- Maximum 255 characters
|
||||
- Cannot start or end with a period
|
||||
|
||||
### name
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
Display name shown to users. Maximum 50 characters.
|
||||
|
||||
```json
|
||||
"name": "My Awesome App"
|
||||
```
|
||||
|
||||
### version
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
Human-readable version string following semantic versioning (MAJOR.MINOR.PATCH).
|
||||
|
||||
```json
|
||||
"version": "1.0.0"
|
||||
"version": "2.1.3-beta"
|
||||
```
|
||||
|
||||
### version_code
|
||||
|
||||
**Type:** `integer`
|
||||
|
||||
Numeric version code that must increase with each release. Used to determine if an update is available.
|
||||
|
||||
```json
|
||||
"version_code": 1
|
||||
```
|
||||
|
||||
Rules:
|
||||
- Must be a positive integer
|
||||
- Must be greater than all previously published versions
|
||||
- Maximum value: 2147483647
|
||||
|
||||
### entry
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
Path to the main RML file, relative to package root.
|
||||
|
||||
```json
|
||||
"entry": "assets/main.rml"
|
||||
```
|
||||
|
||||
### author
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
Information about the app developer.
|
||||
|
||||
```json
|
||||
"author": {
|
||||
"name": "Developer Name",
|
||||
"email": "dev@example.com",
|
||||
"url": "https://example.com"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Developer or company name |
|
||||
| `email` | string | Yes | Contact email |
|
||||
| `url` | string | No | Website URL |
|
||||
|
||||
### icons
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
App icons at various sizes. At minimum, provide a 128px icon.
|
||||
|
||||
```json
|
||||
"icons": {
|
||||
"32": "icons/icon-32.png",
|
||||
"64": "icons/icon-64.png",
|
||||
"128": "icons/icon-128.png"
|
||||
}
|
||||
```
|
||||
|
||||
Supported sizes: 32, 64, 128, 256, 512
|
||||
|
||||
Requirements:
|
||||
- PNG format recommended
|
||||
- Square aspect ratio
|
||||
- No transparency on edges (for proper display)
|
||||
|
||||
## Optional Fields
|
||||
|
||||
### description
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
Short description shown in app listings. Maximum 200 characters.
|
||||
|
||||
```json
|
||||
"description": "A simple calculator for everyday math."
|
||||
```
|
||||
|
||||
### permissions
|
||||
|
||||
**Type:** `array<string>`
|
||||
|
||||
List of permissions your app requires. Apps cannot access restricted features without declaring permissions.
|
||||
|
||||
```json
|
||||
"permissions": ["storage", "network"]
|
||||
```
|
||||
|
||||
See [Permissions](#permissions-reference) below.
|
||||
|
||||
### min_mosis_version
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
Minimum Mosis version required to run this app.
|
||||
|
||||
```json
|
||||
"min_mosis_version": "1.0.0"
|
||||
```
|
||||
|
||||
If omitted, defaults to `"1.0.0"`.
|
||||
|
||||
### category
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
App store category for discovery.
|
||||
|
||||
```json
|
||||
"category": "productivity"
|
||||
```
|
||||
|
||||
Valid categories:
|
||||
- `games`
|
||||
- `entertainment`
|
||||
- `productivity`
|
||||
- `utilities`
|
||||
- `social`
|
||||
- `communication`
|
||||
- `lifestyle`
|
||||
- `education`
|
||||
- `health`
|
||||
- `finance`
|
||||
- `news`
|
||||
- `other`
|
||||
|
||||
### screenshots
|
||||
|
||||
**Type:** `array<string>`
|
||||
|
||||
Paths to screenshot images for app store listing.
|
||||
|
||||
```json
|
||||
"screenshots": [
|
||||
"screenshots/home.png",
|
||||
"screenshots/settings.png",
|
||||
"screenshots/detail.png"
|
||||
]
|
||||
```
|
||||
|
||||
Requirements:
|
||||
- PNG format
|
||||
- 1080x1920 (9:16 portrait) recommended
|
||||
- Maximum 5 screenshots
|
||||
|
||||
### locales
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
Internationalization configuration.
|
||||
|
||||
```json
|
||||
"locales": {
|
||||
"default": "en",
|
||||
"supported": ["en", "es", "fr", "de", "ja"]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `default` | string | Default locale code |
|
||||
| `supported` | array | List of supported locale codes |
|
||||
|
||||
Locale files should be placed in `locales/{code}.json`.
|
||||
|
||||
## Permissions Reference
|
||||
|
||||
| Permission | Description | Example Use |
|
||||
|------------|-------------|-------------|
|
||||
| `storage` | Persist data locally | Save user preferences |
|
||||
| `network` | Make HTTP requests | Fetch remote data |
|
||||
| `clipboard` | Read/write clipboard | Copy text |
|
||||
| `notifications` | Show notifications | Reminders |
|
||||
| `camera` | Access device camera | Photo capture |
|
||||
| `location` | Get device location | Maps, weather |
|
||||
| `contacts` | Read contacts | Contact picker |
|
||||
| `microphone` | Record audio | Voice notes |
|
||||
|
||||
### Permission Declaration
|
||||
|
||||
```json
|
||||
"permissions": [
|
||||
"storage",
|
||||
"network"
|
||||
]
|
||||
```
|
||||
|
||||
Users are informed of permissions before installing. Request only what you need.
|
||||
|
||||
## Validation
|
||||
|
||||
The package builder validates your manifest. Common errors:
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `Invalid package ID` | ID doesn't match pattern | Use `com.company.app` format |
|
||||
| `Missing required field` | Required field omitted | Add the field |
|
||||
| `Invalid version_code` | Not a positive integer | Use positive number |
|
||||
| `Icon not found` | Icon path doesn't exist | Check file paths |
|
||||
| `Invalid permission` | Unknown permission | Use valid permission name |
|
||||
|
||||
## Example: Minimal Manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "com.example.hello",
|
||||
"name": "Hello World",
|
||||
"version": "1.0.0",
|
||||
"version_code": 1,
|
||||
"entry": "main.rml",
|
||||
"author": {
|
||||
"name": "Developer",
|
||||
"email": "dev@example.com"
|
||||
},
|
||||
"icons": {
|
||||
"128": "icon.png"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Example: Full Manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "com.acme.calculator",
|
||||
"name": "ACME Calculator",
|
||||
"version": "2.1.0",
|
||||
"version_code": 5,
|
||||
"entry": "assets/main.rml",
|
||||
"description": "A powerful calculator with scientific functions.",
|
||||
"category": "utilities",
|
||||
"permissions": [
|
||||
"storage",
|
||||
"clipboard"
|
||||
],
|
||||
"min_mosis_version": "1.2.0",
|
||||
"author": {
|
||||
"name": "ACME Corp",
|
||||
"email": "apps@acme.com",
|
||||
"url": "https://acme.com"
|
||||
},
|
||||
"icons": {
|
||||
"32": "icons/icon-32.png",
|
||||
"64": "icons/icon-64.png",
|
||||
"128": "icons/icon-128.png",
|
||||
"256": "icons/icon-256.png"
|
||||
},
|
||||
"screenshots": [
|
||||
"screenshots/basic.png",
|
||||
"screenshots/scientific.png",
|
||||
"screenshots/history.png"
|
||||
],
|
||||
"locales": {
|
||||
"default": "en",
|
||||
"supported": ["en", "es", "fr", "de"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Getting Started](../getting-started.md) - Create your first app
|
||||
- [Permissions Guide](../guides/permissions.md) - Understanding permissions
|
||||
- [Publishing Guide](../guides/publishing.md) - Submit your app
|
||||
Reference in New Issue
Block a user