diff --git a/.editorconfig b/.editorconfig index d2c7a97d..0dbbe70f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,12 +5,11 @@ charset = utf-8 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true -indent_style = tab -indent_size = 4 -tab_width = 4 -[*.{yml,yaml,rs}] +[*.{json,jsonc,json5}] indent_style = space +indent_size = 4 -[*.{yml,yaml}] +[*.{yml,yaml,md}] +indent_style = space indent_size = 2 diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index a62f8f1c..892f4568 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -39,7 +39,7 @@ jobs: - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: ./out + path: ./dist deploy: name: "Deploy" diff --git a/.gitignore b/.gitignore index c5edc4b4..e9a87e5f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,13 @@ /.DS_Store /node_modules /temp -/out -/.next +/dist +/.astro /.env /**/.DS_Store /**/node_modules /**/temp -/**/out -/**/.next +/**/dist +/**/.astro /**/.env diff --git a/app/[[...mdxPath]]/page.jsx b/app/[[...mdxPath]]/page.jsx deleted file mode 100644 index 8c4bd968..00000000 --- a/app/[[...mdxPath]]/page.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import { generateStaticParamsFor, importPage } from "nextra/pages"; -import { useMDXComponents as getMDXComponents } from "../../mdx-components"; - -export const generateStaticParams = generateStaticParamsFor("mdxPath"); - -export async function generateMetadata(props) { - const params = await props.params; - const { metadata } = await importPage(params.mdxPath); - return metadata; -} - -const Wrapper = getMDXComponents().wrapper; - -export default async function Page(props) { - const params = await props.params; - const result = await importPage(params.mdxPath); - const { default: MDXContent, toc, metadata } = result; - return ( - - - - ); -} diff --git a/app/layout.jsx b/app/layout.jsx deleted file mode 100644 index 3a577b67..00000000 --- a/app/layout.jsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Footer, Layout, Navbar } from "nextra-theme-docs"; -import { Head } from "nextra/components"; -import { getPageMap } from "nextra/page-map"; -import "nextra-theme-docs/style.css"; - -export const metadata = {}; - -const navbar = ( - - } - /> -); -const footer = ( - -); - -export default async function RootLayout({ children }) { - return ( - - - - - - - {children} - - - - ); -} diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 00000000..d8aa00c4 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,116 @@ +// @ts-check +import { defineConfig } from "astro/config"; +import starlight from "@astrojs/starlight"; + +// https://astro.build/config +export default defineConfig({ + integrations: [ + starlight({ + title: "Lune", + logo: { + src: "./src/assets/logo.svg", + replacesTitle: true, + }, + social: [ + { + icon: "github", + label: "GitHub", + href: "https://github.com/lune-org/lune", + }, + ], + sidebar: [ + { + label: "Getting Started", + items: [ + { + label: "Installation", + slug: "getting-started/1-installation", + }, + { + label: "Command-Line Usage", + slug: "getting-started/2-command-line-usage", + }, + { + label: "Editor Setup", + slug: "getting-started/3-editor-setup", + }, + { + label: "Security", + slug: "getting-started/4-security", + }, + ], + }, + { + label: "The Lune Book", + items: [ + { + label: "1 ∙ Hello, Lune!", + slug: "the-book/1-hello-lune", + }, + { + label: "2 ∙ Built-In Libraries", + slug: "the-book/2-built-in-libraries", + }, + { + label: "3 ∙ Standard I/O", + slug: "the-book/3-standard-io", + }, + { + label: "4 ∙ Script Arguments", + slug: "the-book/4-script-arguments", + }, + { + label: "5 ∙ Network Requests", + slug: "the-book/5-network-requests", + }, + { + label: "6 ∙ Files & Directories", + slug: "the-book/6-files-and-directories", + }, + { + label: "7 ∙ Environment Variables", + slug: "the-book/7-environment-variables", + }, + { + label: "8 ∙ Modules", + slug: "the-book/8-modules", + }, + { + label: "9 ∙ The Task Scheduler", + slug: "the-book/9-task-scheduler", + }, + { + label: "10 ∙ Spawning Processes", + slug: "the-book/10-spawning-processes", + }, + ], + }, + { + label: "Roblox", + items: [ + { + label: "Introduction", + slug: "roblox/1-introduction", + }, + { + label: "Example Scripts", + slug: "roblox/2-examples", + }, + { + label: "Remodel Migration", + slug: "roblox/3-remodel-migration", + }, + { + label: "API Status", + slug: "roblox/4-api-status", + }, + ], + }, + { + label: "API Reference", + autogenerate: { directory: "api-reference" }, + }, + ], + }), + ], +}); diff --git a/bun.lockb b/bun.lockb index dfd06a40..61c12457 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/content/_meta.js b/content/_meta.js deleted file mode 100644 index b685fa06..00000000 --- a/content/_meta.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - index: "Home", - "getting-started": "Getting Started", - roblox: "Roblox", - "api-reference": "API Reference", -} diff --git a/content/api-reference/_meta.js b/content/api-reference/_meta.js deleted file mode 100644 index db3211ea..00000000 --- a/content/api-reference/_meta.js +++ /dev/null @@ -1,12 +0,0 @@ -export default { - datetime: "DateTime", - fs: "FS", - luau: "Luau", - net: "Net", - process: "Process", - regex: "Regex", - roblox: "Roblox", - serde: "Serde", - stdio: "Stdio", - task: "Task", -} diff --git a/content/api-reference/fs.md b/content/api-reference/fs.md deleted file mode 100644 index 598038ed..00000000 --- a/content/api-reference/fs.md +++ /dev/null @@ -1,279 +0,0 @@ -# FS - -Built-in library for filesystem access - -#### Example usage - -```lua -local fs = require("@lune/fs") - --- Reading a file -local myTextFile: string = fs.readFile("myFileName.txt") - --- Reading entries (files & dirs) in a directory -for _, entryName in fs.readDir("myDirName") do - if fs.isFile("myDirName/" .. entryName) then - print("Found file " .. entryName) - elseif fs.isDir("myDirName/" .. entryName) then - print("Found subdirectory " .. entryName) - end -end -``` - -## Functions - -### readFile - -Reads a file at `path`. - -An error will be thrown in the following situations: - -- `path` does not point to an existing file. -- The current process lacks permissions to read the file. -- Some other I/O error occurred. - -#### Parameters - -- `path` The path to the file to read - -#### Returns - -- The contents of the file - ---- - -### readDir - -Reads entries in a directory at `path`. - -An error will be thrown in the following situations: - -- `path` does not point to an existing directory. -- The current process lacks permissions to read the contents of the directory. -- Some other I/O error occurred. - -#### Parameters - -- `path` The directory path to search in - -#### Returns - -- A list of files & directories found - ---- - -### writeFile - -Writes to a file at `path`. - -An error will be thrown in the following situations: - -- The file's parent directory does not exist. -- The current process lacks permissions to write to the file. -- Some other I/O error occurred. - -#### Parameters - -- `path` The path of the file - -- `contents` The contents of the file - ---- - -### writeDir - -Creates a directory and its parent directories if they are missing. - -An error will be thrown in the following situations: - -- `path` already points to an existing file or directory. -- The current process lacks permissions to create the directory or its missing parents. -- Some other I/O error occurred. - -#### Parameters - -- `path` The directory to create - ---- - -### removeFile - -Removes a file. - -An error will be thrown in the following situations: - -- `path` does not point to an existing file. -- The current process lacks permissions to remove the file. -- Some other I/O error occurred. - -#### Parameters - -- `path` The file to remove - ---- - -### removeDir - -Removes a directory and all of its contents. - -An error will be thrown in the following situations: - -- `path` is not an existing and empty directory. -- The current process lacks permissions to remove the directory. -- Some other I/O error occurred. - -#### Parameters - -- `path` The directory to remove - ---- - -### metadata - -Gets metadata for the given path. - -An error will be thrown in the following situations: - -- The current process lacks permissions to read at `path`. -- Some other I/O error occurred. - -#### Parameters - -- `path` The path to get metadata for - -#### Returns - -- Metadata for the path - ---- - -### isFile - -Checks if a given path is a file. - -An error will be thrown in the following situations: - -- The current process lacks permissions to read at `path`. -- Some other I/O error occurred. - -#### Parameters - -- `path` The file path to check - -#### Returns - -- If the path is a file or not - ---- - -### isDir - -Checks if a given path is a directory. - -An error will be thrown in the following situations: - -- The current process lacks permissions to read at `path`. -- Some other I/O error occurred. - -#### Parameters - -- `path` The directory path to check - -#### Returns - -- If the path is a directory or not - ---- - -### move - -Moves a file or directory to a new path. - -Throws an error if a file or directory already exists at the target path. This can be bypassed by -passing `true` as the third argument, or a dictionary of options. Refer to the documentation for -`WriteOptions` for specific option keys and their values. - -An error will be thrown in the following situations: - -- The current process lacks permissions to read at `from` or write at `to`. -- The new path exists on a different mount point. -- Some other I/O error occurred. - -#### Parameters - -- `from` The path to move from - -- `to` The path to move to - -- `overwriteOrOptions` Options for the target path, such as if should be overwritten if it already - exists - ---- - -### copy - -Copies a file or directory recursively to a new path. - -Throws an error if a file or directory already exists at the target path. This can be bypassed by -passing `true` as the third argument, or a dictionary of options. Refer to the documentation for -`WriteOptions` for specific option keys and their values. - -An error will be thrown in the following situations: - -- The current process lacks permissions to read at `from` or write at `to`. -- Some other I/O error occurred. - -#### Parameters - -- `from` The path to copy from - -- `to` The path to copy to - -- `overwriteOrOptions` Options for the target path, such as if should be overwritten if it already - exists - ---- - -## Types - -### MetadataPermissions - -Permissions for the given file or directory. - -This is a dictionary that will contain the following values: - -- `readOnly` - If the target path is read-only or not - ---- - -### Metadata - -Metadata for the given file or directory. - -This is a dictionary that will contain the following values: - -- `kind` - If the target path is a `file`, `dir` or `symlink` -- `exists` - If the target path exists -- `createdAt` - The timestamp represented as a `DateTime` object at which the file or directory - was created -- `modifiedAt` - The timestamp represented as a `DateTime` object at which the file or directory - was last modified -- `accessedAt` - The timestamp represented as a `DateTime` object at which the file or directory - was last accessed -- `permissions` - Current permissions for the file or directory - -Note that timestamps are relative to the unix epoch, and may not be accurate if the system clock is -not accurate. - ---- - -### WriteOptions - -Options for filesystem APIs what write to files and/or directories. - -This is a dictionary that may contain one or more of the following values: - -- `overwrite` - If the target path should be overwritten or not, in the case that it already - exists - ---- diff --git a/content/getting-started/2-introduction/1-hello-lune.md b/content/getting-started/2-introduction/1-hello-lune.md deleted file mode 100644 index fcd899ea..00000000 --- a/content/getting-started/2-introduction/1-hello-lune.md +++ /dev/null @@ -1,24 +0,0 @@ - - - -# Hello, Lune! - -Congratulations! Lune is now set up and you are ready to start writing scripts 🎉 - -If you've already written some kind of Lua (or Luau) script before, the examples provided in the -overview below should make you feel right at home. They are organized in order of least complex to -most complex, and you don't really have to read them all to understand how Lune works, though it may -help you out. Good luck! - -## Overview - -- `1` [Hello, Lune!](./1-hello-lune.md) (you are here) -- `2` [Built-in Libraries](./2-built-in-libraries.md) -- `3` [Standard I/O](./3-standard-io.mdx) -- `4` [Script Arguments](./4-script-arguments.md) -- `5` [Network Requests](./5-network-requests.mdx) -- `6` [Files & Directories](./6-files-and-directories.mdx) -- `7` [Environment Variables](./7-environment-variables.md) -- `8` [Modules](./8-modules.mdx) -- `9` [Task Scheduler](./9-task-scheduler.mdx) -- `10` [Spawning Processes](./10-spawning-processes.md) diff --git a/content/getting-started/2-introduction/8-modules.mdx b/content/getting-started/2-introduction/8-modules.mdx deleted file mode 100644 index 03208033..00000000 --- a/content/getting-started/2-introduction/8-modules.mdx +++ /dev/null @@ -1,85 +0,0 @@ -import { FileTree, Tabs, Tab, Callout } from "nextra/components"; - -# Modules - -At this point you know how the most important built-in libraries in Lune work and how to use them, -and your code is probably getting longer and more difficult to read. Splitting your code into -multiple files can help you stay organized. - -Modularizing your code and splitting it across several files in Lune is different from other -versions of Lua and Luau, and more similar to how things work in other languages such as JavaScript. - -## Example File Tree - -Let's use this directory & file tree structure for our examples: - - - - - - - - - - - - - - - ```luau copy filename="main.luau" - local sibling = require("sibling") - local modules = require("modules") - - print(sibling.Hello) --> World - - print(modules.Module.Foo) --> Bar - print(modules.Module.Fizz) --> Buzz - - print(modules.Sibling.Hello) --> World - ``` - - - ```luau copy filename="sibling.luau" - return { - Hello = "World", - } - ``` - - - ```luau copy filename="modules/init.luau" - return { - Module = require("module"), - Sibling = require("../sibling"), - } - ``` - - - ```luau copy filename="modules/module.luau" - return { - Foo = "Bar", - Fizz = "Buzz", - } - ``` - - - - -## File Require Statements - -Let's decipher these files and what they are doing: - -- The `main` script requires `sibling` and `modules` next to it -- The `modules/init` script requires `module` next to it, and `sibling` going up one directory - using `../` - -In the above `require` statements, we can see that are relative to the file that they are in, and in -Lune this is always the case, except for built-in libraries, which always start with an at sign -(`@`). - - - **Q:** Wait, hold on... The `main` script requires the _**directory**_ - called `modules`?
- **A:** Yep, that's right. The file name `init` is special, and putting a - file named `init.luau` in a directory will let you use `require` directly on - the directory. Similar to `index.js` in JavaScript or `mod.rs` in Rust. -
diff --git a/content/getting-started/2-introduction/_meta.js b/content/getting-started/2-introduction/_meta.js deleted file mode 100644 index f1d71029..00000000 --- a/content/getting-started/2-introduction/_meta.js +++ /dev/null @@ -1,12 +0,0 @@ -export default { - "1-hello-lune": "1 • Hello, Lune!", - "2-built-in-libraries": "2 • Built-in Libraries", - "3-standard-io": "3 • Standard I/O", - "4-script-arguments": "4 • Script Arguments", - "5-network-requests": "5 • Network Requests", - "6-files-and-directories": "6 • Files & Directories", - "7-environment-variables": "7 • Environment Variables", - "8-modules": "8 • Modules", - "9-task-scheduler": "9 • Task Scheduler", - "10-spawning-processes": "10 • Spawning Processes", -} diff --git a/content/getting-started/5-security.mdx b/content/getting-started/5-security.mdx deleted file mode 100644 index 200051bd..00000000 --- a/content/getting-started/5-security.mdx +++ /dev/null @@ -1,199 +0,0 @@ -import { Steps } from "nextra/components"; - -# Security - -When running lune scripts, it is important to note that any scripts you execute have full access to -your device, including access to your files, programs, and more. Therefore, it is important to stay -cautious when executing a script from a source you don't trust. - -If you are unsure what a script does, it is recommended to run the script in a -[sandboxed]() environment to evaluate what -it does. - -Lune does not include a built-in permissions sandbox, but the following luau script, which utilizes -the [@lune/luau](/api-reference/luau) library can be used for rudimentary sandboxing. It should be noted -that this **does not** guarantee security, and if necessary, you should be running Lune using a containerized -environment such as Docker. - - - -### Step 1 - -Copy the source below and place it in a file named `sandbox.luau`: - -
-Click to expand - -```lua copy -local datetime = require("@lune/datetime") -local fs = require("@lune/fs") -local luau = require("@lune/luau") -local net = require("@lune/net") -local process = require("@lune/process") -local regex = require("@lune/regex") -local roblox = require("@lune/roblox") -local serde = require("@lune/serde") -local stdio = require("@lune/stdio") -local task = require("@lune/task") - -local processArgs = table.clone(process.args) -local filePath: string = table.remove(processArgs, 1) - or error("usage: lune run sandbox [SCRIPT_PATH] -- [ARGS]") - -local DEFAULT_PRINT = print -local SANDBOXED_ENV = { - debugName = filePath, - environment = { - require = nil, - getfenv = nil, - setfenv = nil, - print = nil, - warn = nil, - }, -} - -local PROMPT_MSG_TMPL = `allow {SANDBOXED_ENV.debugName} to access %s?` -local DENIED_ERR_TMPL = `{SANDBOXED_ENV.debugName} tried to access disallowed library %s!` - -local function discoverAndReadScript(filePath: string): string - local scriptContents: string - - if fs.isFile(filePath) then - scriptContents = fs.readFile(filePath) - return scriptContents - end - - if fs.isDir(filePath) then - if fs.isFile(filePath .. "/init.luau") then - scriptContents = fs.readFile(filePath .. "/init.luau") - end - - if fs.isFile(filePath .. "/init.lua") then - scriptContents = fs.readFile(filePath .. "/init.lua") - end - end - - if scriptContents == nil then - for _, ext in { ".luau", ".lua" } do - local filePathExt = filePath .. ext - if fs.isFile(filePathExt) then - scriptContents = fs.readFile(filePathExt) - end - end - - if scriptContents == nil then - error(`No such file or directory \`{filePath}\``) - end - end - - return scriptContents -end - -local function sandboxGetfenv(): {} - if table.isfrozen(SANDBOXED_ENV) then - return SANDBOXED_ENV.environment - end - - return {} -end - -local function sandboxSetfenv(env: {}): never - error("cannot call setfenv from sandbox") -end - -local function sandboxPrint(...: any) - DEFAULT_PRINT(`---- Output from {SANDBOXED_ENV.debugName} ----`) - DEFAULT_PRINT(tostring(...)) - DEFAULT_PRINT(`---------------------------------------`) -end - -local function constructProtectedMt(library: T) - return { - __index = library, - __metatable = "Locked", - __tostring = function() - return stdio.format(library) - end, - } -end - -local SANDBOXED_LUNE_STD_LIB = { - ["@lune/fs"] = setmetatable({}, constructProtectedMt(fs)), - ["@lune/luau"] = setmetatable({}, constructProtectedMt(luau)), - ["@lune/process"] = setmetatable({}, constructProtectedMt(process)), - ["@lune/stdio"] = setmetatable({ - write = sandboxPrint, - ewrite = sandboxPrint, - }, constructProtectedMt(stdio)), - ["@lune/net"] = setmetatable({}, constructProtectedMt(net)), - ["@lune/roblox"] = setmetatable({ - getAuthCookie = function(...) - local allowAuthCookie: boolean = stdio.prompt( - "confirm", - `allow {SANDBOXED_ENV.debugName} to access your .ROBLOSECURITY token?` - ) - - if allowAuthCookie then - local getAuthCookie = require("@lune/roblox").getAuthCookie - return getAuthCookie(...) - end - - error( - `{SANDBOXED_ENV.debugName} attempted to access .ROBLOSECURITY token even when denied` - ) - end, - }, constructProtectedMt(roblox)), - ["@lune/serde"] = serde, - ["@lune/task"] = task, - ["@lune/regex"] = regex, - ["@lune/datetime"] = datetime, -} - -local function sandboxedRequire(path: string) - local module = SANDBOXED_LUNE_STD_LIB[path] - - if module then - local allowed: boolean = stdio.prompt("confirm", string.format(PROMPT_MSG_TMPL, path)) - - if allowed then - return module - end - - error(string.format(DENIED_ERR_TMPL, path)) - else - local contents = discoverAndReadScript(path) - - local evalChunk = luau.load(contents, SANDBOXED_ENV) - return evalChunk() - end -end - -SANDBOXED_ENV.environment.require = sandboxedRequire -SANDBOXED_ENV.environment.getfenv = sandboxGetfenv -SANDBOXED_ENV.environment.setfenv = sandboxSetfenv -SANDBOXED_ENV.environment.print = sandboxPrint -SANDBOXED_ENV.environment.warn = sandboxPrint -luau.load(discoverAndReadScript(filePath), table.freeze(SANDBOXED_ENV))() -``` - -
- -### Step 2 - -Now, place the untrusted script you want to run safely next to the `sandbox.luau` script. - -```sh copy filename="Bash" -lune run sandbox.luau script.luau -- [ARGUMENTS_HERE] -``` - -Replace `script.luau` and `[ARGUMENTS_HERE]` with the path to the script and the arguments to run -it with. - -### Step 3 - -As the script runs, any requires to potentially dangerous modules will require your approval -before continuing and any invocations to methods within approved modules will be logged. - -Furthermore, the output of the sandbox script and the script being run will be separated. - -
diff --git a/content/getting-started/_meta.js b/content/getting-started/_meta.js deleted file mode 100644 index 2fb25860..00000000 --- a/content/getting-started/_meta.js +++ /dev/null @@ -1,7 +0,0 @@ -export default { - "1-installation": "Installation", - "2-introduction": "Introduction", - "3-command-line-usage": "Command-Line Usage", - "4-editor-setup": "Editor Setup", - "5-security": "Security", -} diff --git a/content/roblox/3-remodel-migration.mdx b/content/roblox/3-remodel-migration.mdx deleted file mode 100644 index 2d5d2761..00000000 --- a/content/roblox/3-remodel-migration.mdx +++ /dev/null @@ -1,420 +0,0 @@ -import { Steps } from "nextra/components"; - -# Migrating from Remodel - -If you have used [Remodel](https://github.com/rojo-rbx/remodel) before to manipulate place and/or -model files, this migration guide will help you get started with accomplishing the same tasks in -Lune. - -## Drop-in Compatibility - -This guide provides a module which translates all of the relevant Lune APIs to their Remodel -equivalents. For more details or manual migration steps, check out -[Differences Between Lune & Remodel](#differences-between-lune--remodel) below. - - - -### Step 1 - -Copy the source below and place it in a file named `remodel.luau`: - -
-Click to expand - -```luau copy ---!strict - -local fs = require("@lune/fs") -local net = require("@lune/net") -local serde = require("@lune/serde") -local process = require("@lune/process") -local roblox = require("@lune/roblox") - -export type LuneDataModel = roblox.DataModel -export type LuneInstance = roblox.Instance - -local function getAuthCookieWithFallbacks() - local cookie = roblox.getAuthCookie() - if cookie then - return cookie - end - - local cookieFromEnv = process.env.REMODEL_AUTH - if cookieFromEnv and #cookieFromEnv > 0 then - return `.ROBLOSECURITY={cookieFromEnv}` - end - - for index, arg in process.args do - if arg == "--auth" then - local cookieFromArgs = process.args[index + 1] - if cookieFromArgs and #cookieFromArgs > 0 then - return `.ROBLOSECURITY={cookieFromArgs}` - end - break - end - end - - error([[ - Failed to find ROBLOSECURITY cookie for authentication! - Make sure you have logged into studio, or set the ROBLOSECURITY environment variable. - ]]) -end - -local function downloadAssetId(assetId: number) - -- 1. Try to find the auth cookie for the current user - local cookie = getAuthCookieWithFallbacks() - - -- 2. Send a request to the asset delivery API, - -- which will respond with cdn download link(s) - local assetApiResponse = net.request({ - url = `https://assetdelivery.roblox.com/v2/assetId/{assetId}`, - headers = { - Accept = "application/json", - Cookie = cookie, - }, - }) - if not assetApiResponse.ok then - error( - string.format( - "Failed to fetch asset download link for asset id %s!\n%s (%s)\n%s", - tostring(assetId), - tostring(assetApiResponse.statusCode), - tostring(assetApiResponse.statusMessage), - tostring(assetApiResponse.body) - ) - ) - end - - -- 3. Make sure we got a valid response body - local assetApiBody = serde.decode("json", assetApiResponse.body) - if type(assetApiBody) ~= "table" then - error( - string.format( - "Asset delivery API returned an invalid response body!\n%s", - assetApiResponse.body - ) - ) - elseif type(assetApiBody.locations) ~= "table" then - error( - string.format( - "Asset delivery API returned an invalid response body!\n%s", - assetApiResponse.body - ) - ) - end - - -- 4. Grab the first asset download location - we only - -- requested one in our query, so this will be correct - local firstLocation = assetApiBody.locations[1] - if type(firstLocation) ~= "table" then - error( - string.format( - "Asset delivery API returned no download locations!\n%s", - assetApiResponse.body - ) - ) - elseif type(firstLocation.location) ~= "string" then - error( - string.format( - "Asset delivery API returned no valid download locations!\n%s", - assetApiResponse.body - ) - ) - end - - -- 5. Fetch the place contents from the cdn - local cdnResponse = net.request({ - url = firstLocation.location, - headers = { - Cookie = cookie, - }, - }) - if not cdnResponse.ok then - error( - string.format( - "Failed to download asset with id %s from the Roblox cdn!\n%s (%s)\n%s", - tostring(assetId), - tostring(cdnResponse.statusCode), - tostring(cdnResponse.statusMessage), - tostring(cdnResponse.body) - ) - ) - end - - -- 6. The response body should now be the contents of the asset file - return cdnResponse.body -end - -local function uploadAssetId(assetId: number, contents: string) - -- 1. Try to find the auth cookie for the current user - local cookie = getAuthCookieWithFallbacks() - - -- 2. Use a different endpoint to fetch a valid CSRF token - local csrfHeaders = { - ["User-Agent"] = "Roblox/WinInet", - Accept = "application/json", - Cookie = cookie, - } - - local csrfResponse = net.request({ - url = `https://auth.roblox.com/`, - body = contents, - method = "POST", - headers = csrfHeaders, - }) - - local csrfToken = csrfResponse.headers["x-csrf-token"] - if csrfToken == nil then error('Failed to fetch CSRF token.') end - - -- 3. Upload the asset to Roblox - local uploadHeaders = { - ["User-Agent"] = "Roblox/WinInet", - ["Content-Type"] = "application/octet-stream", - ['X-CSRF-Token'] = csrfToken, - Accept = "application/json", - Cookie = cookie, - } - - local uploadResponse = net.request({ - url = `https://data.roblox.com/Data/Upload.ashx?assetid={assetId}`, - body = contents, - method = "POST", - headers = uploadHeaders, - }) - - -- 4. Make sure it uploaded properly - if not uploadResponse.ok then - error( - string.format( - "Failed to upload asset with id %s to Roblox!\n%s (%s)\n%s", - tostring(assetId), - tostring(uploadResponse.statusCode), - tostring(uploadResponse.statusMessage), - tostring(uploadResponse.body) - ) - ) - end -end - -local remodel = {} - ---[=[ - Load an `rbxl` or `rbxlx` file from the filesystem. - - Returns a `DataModel` instance, equivalent to `game` from within Roblox. -]=] -function remodel.readPlaceFile(filePath: string) - local placeFile = fs.readFile(filePath) - local place = roblox.deserializePlace(placeFile) - return place -end - ---[=[ - Load an `rbxm` or `rbxmx` file from the filesystem. - - Note that this function returns a **list of instances** instead of a single instance! - This is because models can contain mutliple top-level instances. -]=] -function remodel.readModelFile(filePath: string) - local modelFile = fs.readFile(filePath) - local model = roblox.deserializeModel(modelFile) - return model -end - ---[=[ - Reads a place asset from Roblox, equivalent to `remodel.readPlaceFile`. - - ***NOTE:** This function requires authentication using a ROBLOSECURITY cookie!* -]=] -function remodel.readPlaceAsset(assetId: number) - local contents = downloadAssetId(assetId) - local place = roblox.deserializePlace(contents) - return place -end - ---[=[ - Reads a model asset from Roblox, equivalent to `remodel.readModelFile`. - - ***NOTE:** This function requires authentication using a ROBLOSECURITY cookie!* -]=] -function remodel.readModelAsset(assetId: number) - local contents = downloadAssetId(assetId) - local place = roblox.deserializeModel(contents) - return place -end - ---[=[ - Saves an `rbxl` or `rbxlx` file out of the given `DataModel` instance. - - If the instance is not a `DataModel`, this function will throw. - Models should be saved with `writeModelFile` instead. -]=] -function remodel.writePlaceFile(filePath: string, dataModel: LuneDataModel) - local asBinary = string.sub(filePath, -5) == ".rbxl" - local asXml = string.sub(filePath, -6) == ".rbxlx" - assert(asBinary or asXml, "File path must have .rbxl or .rbxlx extension") - local placeFile = roblox.serializePlace(dataModel, asXml) - fs.writeFile(filePath, placeFile) -end - ---[=[ - Saves an `rbxm` or `rbxmx` file out of the given `Instance`. - - If the instance is a `DataModel`, this function will throw. - Places should be saved with `writePlaceFile` instead. -]=] -function remodel.writeModelFile(filePath: string, instance: LuneInstance) - local asBinary = string.sub(filePath, -5) == ".rbxm" - local asXml = string.sub(filePath, -6) == ".rbxmx" - assert(asBinary or asXml, "File path must have .rbxm or .rbxmx extension") - local placeFile = roblox.serializeModel({ instance }, asXml) - fs.writeFile(filePath, placeFile) -end - ---[=[ - Uploads the given `DataModel` instance to Roblox, overwriting an existing place. - - If the instance is not a `DataModel`, this function will throw. - Models should be uploaded with `writeExistingModelAsset` instead. - - ***NOTE:** This function requires authentication using a ROBLOSECURITY cookie!* -]=] -function remodel.writeExistingPlaceAsset(dataModel: LuneDataModel, assetId: number) - local placeFile = roblox.serializePlace(dataModel) - uploadAssetId(assetId, placeFile) -end - ---[=[ - Uploads the given instance to Roblox, overwriting an existing model. - - If the instance is a `DataModel`, this function will throw. - Places should be uploaded with `writeExistingPlaceAsset` instead. - - ***NOTE:** This function requires authentication using a ROBLOSECURITY cookie!* -]=] -function remodel.writeExistingModelAsset(instance: LuneInstance, assetId: number) - local modelFile = roblox.serializeModel({ instance }) - uploadAssetId(assetId, modelFile) -end - -remodel.readFile = fs.readFile -remodel.readDir = fs.readDir -remodel.writeFile = fs.writeFile -remodel.createDirAll = fs.writeDir -remodel.removeFile = fs.removeFile -remodel.removeDir = fs.removeDir -remodel.isFile = fs.isFile -remodel.isDir = fs.isDir - -return remodel -``` - -
- -This module is quite large, but you will not need to read through it unless you want to know about -the internal details of how Remodel used to work. - -### Step 2 - -Next, create another script next to your `remodel.luau`. We will be naming it `example.luau`, but -you can name it whatever you want. This example code is from one of the previous Remodel-native -example scripts, with only the top line added: - -```luau copy -local remodel = require("./remodel") - --- One use for Remodel is to move the terrain of one place into another place. -local inputGame = remodel.readPlaceFile("input-place.rbxlx") -local outputGame = remodel.readPlaceFile("output-place.rbxlx") - --- This isn't possible inside Roblox, but works just fine in Remodel! -outputGame.Workspace.Terrain:Destroy() -inputGame.Workspace.Terrain.Parent = outputGame.Workspace - -remodel.writePlaceFile("output-place-updated.rbxlx", outputGame) -``` - -### Step 3 - -Finally, run the script you've created by providing the script name to Lune, in our case `example`, -without the luau file extension. Everything should work the same way it did when running natively in -Remodel, now running in Lune 🚀 - -```sh copy -lune run example -``` - -
- -## Differences Between Lune & Remodel - -Most APIs previously found in Remodel have direct equivalents in Lune, below are some direct links -to APIs that are equivalent or very similar. - -
-Places & Models - -- `remodel.readPlaceFile` ➡ [`fs.readFile`](../api-reference/fs.md#readfile) & - [`roblox.deserializePlace`](../api-reference/roblox.md#deserializeplace) -- `remodel.readModelFile` ➡ [`fs.readFile`](../api-reference/fs.md#readfile) & - [`roblox.deserializeModel`](../api-reference/roblox.md#deserializemodel) -- `remodel.readPlaceAsset` ➡ [`net.request`](../api-reference/net.md#request) & - [`roblox.deserializePlace`](../api-reference/roblox.md#deserializeplace) -- `remodel.readModelAsset` ➡ [`net.request`](../api-reference/net.md#request) & - [`roblox.deserializeModel`](../api-reference/roblox.md#deserializemodel) -- `remodel.writePlaceFile` ➡ [`roblox.serializePlace`](../api-reference/roblox.md#serializeplace) - & [`fs.writeFile`](../api-reference/fs.md#writefile) -- `remodel.writeModelFile` ➡ [`roblox.serializeModel`](../api-reference/roblox.md#serializemodel) - & [`fs.writeFile`](../api-reference/fs.md#writefile) -- `remodel.writeExistingPlaceAsset` ➡ - [`roblox.serializePlace`](../api-reference/roblox.md#serializeplace) & - [`net.request`](../api-reference/net.md#request) -- `remodel.writeExistingModelAsset` ➡ - [`roblox.serializeModel`](../api-reference/roblox.md#serializemodel) & - [`net.request`](../api-reference/net.md#request) -- `remodel.getRawProperty` ➡ no equivalent, you can get properties directly by indexing -- `remodel.setRawProperty` ➡ no equivalent, you can set properties directly by indexing - -
- -
-Files & Directories - -- `remodel.readFile` ➡ [`fs.readFile`](../api-reference/fs.md#readfile) -- `remodel.readDir` ➡ [`fs.readDir`](../api-reference/fs.md#readdir) -- `remodel.writeFile` ➡ [`fs.writeFile`](../api-reference/fs.md#writefile) -- `remodel.createDirAll` ➡ [`fs.writeDir`](../api-reference/fs.md#writedir) -- `remodel.removeFile` ➡ [`fs.removeFile`](../api-reference/fs.md#removefile) -- `remodel.removeDir` ➡ [`fs.removeDir`](../api-reference/fs.md#removedir) -- `remodel.isFile` ➡ [`fs.isFile`](../api-reference/fs.md#isfile) -- `remodel.isDir` ➡ [`fs.isDir`](../api-reference/fs.md#isdir) - -
- -
-JSON - -- `json.fromString` ➡ [`serde.decode`](../api-reference/serde.md#decode) -- `json.toString` ➡ [`serde.encode`](../api-reference/serde.md#encode) -- `json.toStringPretty` ➡ [`serde.encode`](../api-reference/serde.md#encode) - -
- -Since Lune is meant to be a general-purpose Luau runtime, there are also some more general -differences, and Lune takes a different approach from Remodel in certain areas: - -- Lune runs Luau instead of Lua 5.3. -- APIs are more loosely coupled, meaning that a task may require more steps using Lune. This also - means that Lune is more flexible and supports more use cases. -- Built-in libraries are not accessible from global variables, you have to explicitly import them - using `require("@lune/library-name")`. -- Arguments given to scripts are not available in `...`, you have to use - [`process.args`](../api-reference/process.md#args) instead. -- Lune generally supports all of the Roblox datatypes that are gettable/settable on instance - properties. For a full list of available datatypes, check out the - [API Status](./4-api-status.md) page. - ---- - -There may be more differences than are listed here, and the Lune-specific guides and examples may -provide more info, but this should be all you need to know to migrate from Remodel. Good luck! diff --git a/content/roblox/_meta.js b/content/roblox/_meta.js deleted file mode 100644 index 92c1715c..00000000 --- a/content/roblox/_meta.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - "1-introduction": "Introduction", - "2-examples": "Examples", - "3-remodel-migration": "Migrating from Remodel", - "4-api-status": "API Status", -} diff --git a/mdx-components.js b/mdx-components.js deleted file mode 100644 index c781d447..00000000 --- a/mdx-components.js +++ /dev/null @@ -1,10 +0,0 @@ -import { useMDXComponents as getThemeComponents } from "nextra-theme-docs" - -const themeComponents = getThemeComponents() - -export function useMDXComponents(components) { - return { - ...themeComponents, - ...components, - } -} diff --git a/next-env.d.ts b/next-env.d.ts deleted file mode 100644 index 1b3be084..00000000 --- a/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.mjs b/next.config.mjs deleted file mode 100644 index 60d84fb2..00000000 --- a/next.config.mjs +++ /dev/null @@ -1,16 +0,0 @@ -import nextra from "nextra" - -const withNextra = nextra({}) - -/** - * @type {import('next').NextConfig} - */ -const nextConfig = { - output: "export", - basePath: "/docs", - images: { - unoptimized: true, - }, -} - -export default withNextra(nextConfig) diff --git a/package.json b/package.json index 1c8db336..138a2e6c 100644 --- a/package.json +++ b/package.json @@ -1,31 +1,20 @@ { - "name": "lune-docs", - "version": "0.0.1", - "description": "Documentation site for Lune", - "scripts": { - "dev": "next", - "build": "next build", - "start": "next start" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lune-org/docs.git" - }, - "bugs": { - "url": "https://github.com/lune-orc/docs/issues" - }, - "homepage": "https://github.com/lune-orc/docs#readme", - "dependencies": { - "next": "^15.4.1", - "nextra": "^4.2.17", - "nextra-theme-docs": "^4.2.17", - "react": "^19.1.0", - "react-dom": "^19.1.0" - }, - "devDependencies": { - "@types/node": "^22.16.4", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", - "typescript": "5.8.3" - } + "name": "starlight", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/starlight": "^0.34.6", + "astro": "^5.6.1", + "sharp": "^0.34.2" + }, + "devDependencies": { + "prettier": "^3.6.2" + } } diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 00000000..fef2657b --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 00000000..fef2657b --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/content.config.ts b/src/content.config.ts new file mode 100644 index 00000000..a3a36421 --- /dev/null +++ b/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from "astro:content"; +import { docsLoader } from "@astrojs/starlight/loaders"; +import { docsSchema } from "@astrojs/starlight/schema"; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/content/api-reference/datetime.md b/src/content/docs/api-reference/datetime.md similarity index 77% rename from content/api-reference/datetime.md rename to src/content/docs/api-reference/datetime.md index e391e0ee..9b2b25cf 100644 --- a/content/api-reference/datetime.md +++ b/src/content/docs/api-reference/datetime.md @@ -1,4 +1,6 @@ -# DateTime +--- +title: DateTime +--- Built-in library for date & time @@ -48,7 +50,7 @@ Returns a `DateTime` representing the current moment in time. #### Returns -- `DateTime` The new DateTime object +- `DateTime` The new DateTime object --- @@ -61,19 +63,19 @@ milliseconds / nanoseconds. Example usage of fractions: -- `DateTime.fromUnixTimestamp(123456789.001)` - one millisecond -- `DateTime.fromUnixTimestamp(123456789.000000001)` - one nanosecond +- `DateTime.fromUnixTimestamp(123456789.001)` - one millisecond +- `DateTime.fromUnixTimestamp(123456789.000000001)` - one nanosecond Note that the fractional part has limited precision down to exactly one nanosecond, any fraction that is more precise will get truncated. #### Parameters -- `unixTimestamp` `number` Seconds passed since the UNIX epoch +- `unixTimestamp` `number` Seconds passed since the UNIX epoch #### Returns -- `DateTime` The new DateTime object +- `DateTime` The new DateTime object --- @@ -101,16 +103,16 @@ Any non-integer values in the given table will be rounded down. This constructor is fallible and may throw an error in the following situations: -- Date units (year, month, day) were given that produce an invalid date. For example, January 32nd - or February 29th on a non-leap year. +- Date units (year, month, day) were given that produce an invalid date. For example, January 32nd + or February 29th on a non-leap year. #### Parameters -- `values` `DateTimeValueArguments` Table containing date & time values +- `values` `DateTimeValueArguments` Table containing date & time values #### Returns -- `DateTime` The new DateTime object +- `DateTime` The new DateTime object --- @@ -138,16 +140,16 @@ Any non-integer values in the given table will be rounded down. This constructor is fallible and may throw an error in the following situations: -- Date units (year, month, day) were given that produce an invalid date. For example, January 32nd - or February 29th on a non-leap year. +- Date units (year, month, day) were given that produce an invalid date. For example, January 32nd + or February 29th on a non-leap year. #### Parameters -- `values` `DateTimeValueArguments` Table containing date & time values +- `values` `DateTimeValueArguments` Table containing date & time values #### Returns -- `DateTime` The new DateTime object +- `DateTime` The new DateTime object --- @@ -162,17 +164,17 @@ ISO 8601 date-time string format. Some examples of valid ISO 8601 date-time strings are: -- `2020-02-22T18:12:08Z` -- `2000-01-31T12:34:56+05:00` -- `1970-01-01T00:00:00.055Z` +- `2020-02-22T18:12:08Z` +- `2000-01-31T12:34:56+05:00` +- `1970-01-01T00:00:00.055Z` #### Parameters -- `isoDate` `string` An ISO 8601 formatted string +- `isoDate` `string` An ISO 8601 formatted string #### Returns -- `DateTime` The new DateTime object +- `DateTime` The new DateTime object --- @@ -202,15 +204,15 @@ If not provided, `formatString` and `locale` will default to `"%Y-%m-%d %H:%M:%S #### Parameters -- `self` DateTime +- `self` DateTime -- `formatString` `string?` A string containing formatting tokens +- `formatString` `string?` A string containing formatting tokens -- `locale` `Locale?` The locale the time should be formatted in +- `locale` `Locale?` The locale the time should be formatted in #### Returns -- `string` The formatting string +- `string` The formatting string --- @@ -238,15 +240,15 @@ If not provided, `formatString` and `locale` will default to `"%Y-%m-%d %H:%M:%S #### Parameters -- `self` DateTime +- `self` DateTime -- `formatString` `string?` A string containing formatting tokens +- `formatString` `string?` A string containing formatting tokens -- `locale` `Locale?` The locale the time should be formatted in +- `locale` `Locale?` The locale the time should be formatted in #### Returns -- `string` The formatting string +- `string` The formatting string --- @@ -256,17 +258,17 @@ Formats this `DateTime` as an ISO 8601 date-time string. Some examples of ISO 8601 date-time strings are: -- `2020-02-22T18:12:08Z` -- `2000-01-31T12:34:56+05:00` -- `1970-01-01T00:00:00.055Z` +- `2020-02-22T18:12:08Z` +- `2000-01-31T12:34:56+05:00` +- `1970-01-01T00:00:00.055Z` #### Parameters -- `self` DateTime +- `self` DateTime #### Returns -- `string` The ISO 8601 formatted string +- `string` The ISO 8601 formatted string --- @@ -288,11 +290,11 @@ The returned table contains the following values: #### Parameters -- `self` DateTime +- `self` DateTime #### Returns -- `DateTimeValueReturns` A table of DateTime values +- `DateTimeValueReturns` A table of DateTime values --- @@ -314,11 +316,11 @@ The returned table contains the following values: #### Parameters -- `self` DateTime +- `self` DateTime #### Returns -- `DateTimeValueReturns` A table of DateTime values +- `DateTimeValueReturns` A table of DateTime values --- @@ -330,16 +332,16 @@ Enum type representing supported DateTime locales. Currently supported locales are: -- `en` - English -- `de` - German -- `es` - Spanish -- `fr` - French -- `it` - Italian -- `ja` - Japanese -- `pl` - Polish -- `pt-br` - Brazilian Portuguese -- `pt` - Portuguese -- `tr` - Turkish +- `en` - English +- `de` - German +- `es` - Spanish +- `fr` - French +- `it` - Italian +- `ja` - Japanese +- `pl` - Polish +- `pt-br` - Brazilian Portuguese +- `pt` - Portuguese +- `tr` - Turkish --- @@ -349,12 +351,12 @@ Individual date & time values, representing the primitives that make up a `DateT This is a dictionary that will contain the following values: -- `year` - Year(s), in the range 1400 -> 9999 -- `month` - Month(s), in the range 1 -> 12 -- `day` - Day(s), in the range 1 -> 31 -- `hour` - Hour(s), in the range 0 -> 23 -- `minute` - Minute(s), in the range 0 -> 59 -- `second` - Second(s), in the range 0 -> 60, where 60 is a leap second +- `year` - Year(s), in the range 1400 -> 9999 +- `month` - Month(s), in the range 1 -> 12 +- `day` - Day(s), in the range 1 -> 31 +- `hour` - Hour(s), in the range 0 -> 23 +- `minute` - Minute(s), in the range 0 -> 59 +- `second` - Second(s), in the range 0 -> 60, where 60 is a leap second An additional `millisecond` value may also be included, and should be within the range `0 -> 999`, but is optional. diff --git a/src/content/docs/api-reference/fs.md b/src/content/docs/api-reference/fs.md new file mode 100644 index 00000000..305791d7 --- /dev/null +++ b/src/content/docs/api-reference/fs.md @@ -0,0 +1,281 @@ +--- +title: FS +--- + +Built-in library for filesystem access + +#### Example usage + +```lua +local fs = require("@lune/fs") + +-- Reading a file +local myTextFile: string = fs.readFile("myFileName.txt") + +-- Reading entries (files & dirs) in a directory +for _, entryName in fs.readDir("myDirName") do + if fs.isFile("myDirName/" .. entryName) then + print("Found file " .. entryName) + elseif fs.isDir("myDirName/" .. entryName) then + print("Found subdirectory " .. entryName) + end +end +``` + +## Functions + +### readFile + +Reads a file at `path`. + +An error will be thrown in the following situations: + +- `path` does not point to an existing file. +- The current process lacks permissions to read the file. +- Some other I/O error occurred. + +#### Parameters + +- `path` The path to the file to read + +#### Returns + +- The contents of the file + +--- + +### readDir + +Reads entries in a directory at `path`. + +An error will be thrown in the following situations: + +- `path` does not point to an existing directory. +- The current process lacks permissions to read the contents of the directory. +- Some other I/O error occurred. + +#### Parameters + +- `path` The directory path to search in + +#### Returns + +- A list of files & directories found + +--- + +### writeFile + +Writes to a file at `path`. + +An error will be thrown in the following situations: + +- The file's parent directory does not exist. +- The current process lacks permissions to write to the file. +- Some other I/O error occurred. + +#### Parameters + +- `path` The path of the file + +- `contents` The contents of the file + +--- + +### writeDir + +Creates a directory and its parent directories if they are missing. + +An error will be thrown in the following situations: + +- `path` already points to an existing file or directory. +- The current process lacks permissions to create the directory or its missing parents. +- Some other I/O error occurred. + +#### Parameters + +- `path` The directory to create + +--- + +### removeFile + +Removes a file. + +An error will be thrown in the following situations: + +- `path` does not point to an existing file. +- The current process lacks permissions to remove the file. +- Some other I/O error occurred. + +#### Parameters + +- `path` The file to remove + +--- + +### removeDir + +Removes a directory and all of its contents. + +An error will be thrown in the following situations: + +- `path` is not an existing and empty directory. +- The current process lacks permissions to remove the directory. +- Some other I/O error occurred. + +#### Parameters + +- `path` The directory to remove + +--- + +### metadata + +Gets metadata for the given path. + +An error will be thrown in the following situations: + +- The current process lacks permissions to read at `path`. +- Some other I/O error occurred. + +#### Parameters + +- `path` The path to get metadata for + +#### Returns + +- Metadata for the path + +--- + +### isFile + +Checks if a given path is a file. + +An error will be thrown in the following situations: + +- The current process lacks permissions to read at `path`. +- Some other I/O error occurred. + +#### Parameters + +- `path` The file path to check + +#### Returns + +- If the path is a file or not + +--- + +### isDir + +Checks if a given path is a directory. + +An error will be thrown in the following situations: + +- The current process lacks permissions to read at `path`. +- Some other I/O error occurred. + +#### Parameters + +- `path` The directory path to check + +#### Returns + +- If the path is a directory or not + +--- + +### move + +Moves a file or directory to a new path. + +Throws an error if a file or directory already exists at the target path. This can be bypassed by +passing `true` as the third argument, or a dictionary of options. Refer to the documentation for +`WriteOptions` for specific option keys and their values. + +An error will be thrown in the following situations: + +- The current process lacks permissions to read at `from` or write at `to`. +- The new path exists on a different mount point. +- Some other I/O error occurred. + +#### Parameters + +- `from` The path to move from + +- `to` The path to move to + +- `overwriteOrOptions` Options for the target path, such as if should be overwritten if it already + exists + +--- + +### copy + +Copies a file or directory recursively to a new path. + +Throws an error if a file or directory already exists at the target path. This can be bypassed by +passing `true` as the third argument, or a dictionary of options. Refer to the documentation for +`WriteOptions` for specific option keys and their values. + +An error will be thrown in the following situations: + +- The current process lacks permissions to read at `from` or write at `to`. +- Some other I/O error occurred. + +#### Parameters + +- `from` The path to copy from + +- `to` The path to copy to + +- `overwriteOrOptions` Options for the target path, such as if should be overwritten if it already + exists + +--- + +## Types + +### MetadataPermissions + +Permissions for the given file or directory. + +This is a dictionary that will contain the following values: + +- `readOnly` - If the target path is read-only or not + +--- + +### Metadata + +Metadata for the given file or directory. + +This is a dictionary that will contain the following values: + +- `kind` - If the target path is a `file`, `dir` or `symlink` +- `exists` - If the target path exists +- `createdAt` - The timestamp represented as a `DateTime` object at which the file or directory + was created +- `modifiedAt` - The timestamp represented as a `DateTime` object at which the file or directory + was last modified +- `accessedAt` - The timestamp represented as a `DateTime` object at which the file or directory + was last accessed +- `permissions` - Current permissions for the file or directory + +Note that timestamps are relative to the unix epoch, and may not be accurate if the system clock is +not accurate. + +--- + +### WriteOptions + +Options for filesystem APIs what write to files and/or directories. + +This is a dictionary that may contain one or more of the following values: + +- `overwrite` - If the target path should be overwritten or not, in the case that it already + exists + +--- diff --git a/content/api-reference/luau.md b/src/content/docs/api-reference/luau.md similarity index 64% rename from content/api-reference/luau.md rename to src/content/docs/api-reference/luau.md index 80a8369f..0c1d0127 100644 --- a/content/api-reference/luau.md +++ b/src/content/docs/api-reference/luau.md @@ -1,4 +1,6 @@ -# Luau +--- +title: Luau +--- Built-in library for generating luau bytecode & functions. @@ -42,13 +44,13 @@ local bytecode = luau.compile("print('Hello, World!')", { #### Parameters -- `source` The string that will be compiled into bytecode +- `source` The string that will be compiled into bytecode -- `compileOptions` The options passed to the luau compiler that will output the bytecode +- `compileOptions` The options passed to the luau compiler that will output the bytecode #### Returns -- luau bytecode +- luau bytecode --- @@ -73,13 +75,13 @@ callableFn() #### Parameters -- `source` Either luau bytecode or string source code +- `source` Either luau bytecode or string source code -- `loadOptions` The options passed to luau for loading the chunk +- `loadOptions` The options passed to luau for loading the chunk #### Returns -- luau chunk +- luau chunk --- @@ -91,9 +93,9 @@ The options passed to the luau compiler while compiling bytecode. This is a dictionary that may contain one or more of the following values: -- `optimizationLevel` - Sets the compiler option "optimizationLevel". Defaults to `1`. -- `coverageLevel` - Sets the compiler option "coverageLevel". Defaults to `0`. -- `debugLevel` - Sets the compiler option "debugLevel". Defaults to `1`. +- `optimizationLevel` - Sets the compiler option "optimizationLevel". Defaults to `1`. +- `coverageLevel` - Sets the compiler option "coverageLevel". Defaults to `0`. +- `debugLevel` - Sets the compiler option "debugLevel". Defaults to `1`. Documentation regarding what these values represent can be found [here](https://github.com/Roblox/luau/blob/bd229816c0a82a8590395416c81c333087f541fd/Compiler/include/luacode.h#L13-L39). @@ -106,11 +108,11 @@ The options passed while loading a luau chunk from an arbitrary string, or bytec This is a dictionary that may contain one or more of the following values: -- `debugName` - The debug name of the closure. Defaults to `luau.load(...)`. -- `environment` - A custom environment to load the chunk in. Setting a custom environment will - deoptimize the chunk and forcefully disable codegen. Defaults to the global environment. -- `injectGlobals` - Whether or not to inject globals in the custom environment. Has no effect if - no custom environment is provided. Defaults to `true`. -- `codegenEnabled` - Whether or not to enable codegen. Defaults to `false`. +- `debugName` - The debug name of the closure. Defaults to `luau.load(...)`. +- `environment` - A custom environment to load the chunk in. Setting a custom environment will + deoptimize the chunk and forcefully disable codegen. Defaults to the global environment. +- `injectGlobals` - Whether or not to inject globals in the custom environment. Has no effect if + no custom environment is provided. Defaults to `true`. +- `codegenEnabled` - Whether or not to enable codegen. Defaults to `false`. --- diff --git a/content/api-reference/net.md b/src/content/docs/api-reference/net.md similarity index 53% rename from content/api-reference/net.md rename to src/content/docs/api-reference/net.md index 3c5f2853..df615159 100644 --- a/content/api-reference/net.md +++ b/src/content/docs/api-reference/net.md @@ -1,4 +1,6 @@ -# Net +--- +title: Net +--- Built-in library for network access @@ -46,11 +48,11 @@ codes. #### Parameters -- `config` The URL or request config to use +- `config` The URL or request config to use #### Returns -- A dictionary representing the response for the request +- A dictionary representing the response for the request --- @@ -63,11 +65,11 @@ network or I/O error occurs. #### Parameters -- `url` The URL to connect to +- `url` The URL to connect to #### Returns -- A web socket handle +- A web socket handle --- @@ -80,13 +82,13 @@ function on the returned `ServeHandle` has been called. #### Parameters -- `port` The port to use for the server +- `port` The port to use for the server -- `handlerOrConfig` The handler function or config to use for the server +- `handlerOrConfig` The handler function or config to use for the server #### Returns -- ServeHandle +- ServeHandle --- @@ -96,13 +98,13 @@ Encodes the given value as JSON. #### Parameters -- `value` The value to encode as JSON +- `value` The value to encode as JSON -- `pretty` If the encoded JSON string should include newlines and spaces. Defaults to false +- `pretty` If the encoded JSON string should include newlines and spaces. Defaults to false #### Returns -- The encoded JSON string +- The encoded JSON string --- @@ -112,11 +114,11 @@ Decodes the given JSON string into a lua value. #### Parameters -- `encoded` The JSON string to decode +- `encoded` The JSON string to decode #### Returns -- The decoded lua value +- The decoded lua value --- @@ -126,14 +128,14 @@ Encodes the given string using URL encoding. #### Parameters -- `s` The string to encode +- `s` The string to encode -- `binary` If the string should be treated as binary data and/or is not valid utf-8. Defaults to - false +- `binary` If the string should be treated as binary data and/or is not valid utf-8. Defaults to + false #### Returns -- The encoded string +- The encoded string --- @@ -143,14 +145,14 @@ Decodes the given string using URL decoding. #### Parameters -- `s` The string to decode +- `s` The string to decode -- `binary` If the string should be treated as binary data and/or is not valid utf-8. Defaults to - false +- `binary` If the string should be treated as binary data and/or is not valid utf-8. Defaults to + false #### Returns -- The decoded string +- The decoded string --- @@ -162,8 +164,8 @@ Extra options for `FetchParams`. This is a dictionary that may contain one or more of the following values: -- `decompress` - If the request body should be automatically decompressed when possible. Defaults - to `true` +- `decompress` - If the request body should be automatically decompressed when possible. Defaults + to `true` --- @@ -173,13 +175,13 @@ Parameters for sending network requests with `net.request`. This is a dictionary that may contain one or more of the following values: -- `url` - The URL to send a request to. This is always required -- `method` - The HTTP method verb, such as `"GET"`, `"POST"`, `"PATCH"`, `"PUT"`, or `"DELETE"`. - Defaults to `"GET"` -- `body` - The request body -- `query` - A table of key-value pairs representing query parameters in the request path -- `headers` - A table of key-value pairs representing headers -- `options` - Extra options for things such as automatic decompression of response bodies +- `url` - The URL to send a request to. This is always required +- `method` - The HTTP method verb, such as `"GET"`, `"POST"`, `"PATCH"`, `"PUT"`, or `"DELETE"`. + Defaults to `"GET"` +- `body` - The request body +- `query` - A table of key-value pairs representing query parameters in the request path +- `headers` - A table of key-value pairs representing headers +- `options` - Extra options for things such as automatic decompression of response bodies --- @@ -189,13 +191,13 @@ Response type for sending network requests with `net.request`. This is a dictionary containing the following values: -- `ok` - If the status code is a canonical success status code, meaning within the range 200 -> - 299 -- `statusCode` - The status code returned for the request -- `statusMessage` - The canonical status message for the returned status code, such as - `"Not Found"` for status code 404 -- `headers` - A table of key-value pairs representing headers -- `body` - The request body, or an empty string if one was not given +- `ok` - If the status code is a canonical success status code, meaning within the range 200 -> + 299 +- `statusCode` - The status code returned for the request +- `statusMessage` - The canonical status message for the returned status code, such as + `"Not Found"` for status code 404 +- `headers` - A table of key-value pairs representing headers +- `body` - The request body, or an empty string if one was not given --- @@ -205,12 +207,12 @@ Data type for requests in `net.serve`. This is a dictionary containing the following values: -- `path` - The path being requested, relative to the root. Will be `/` if not specified -- `query` - A table of key-value pairs representing query parameters in the request path -- `method` - The HTTP method verb, such as `"GET"`, `"POST"`, `"PATCH"`, `"PUT"`, or `"DELETE"`. - Will always be uppercase -- `headers` - A table of key-value pairs representing headers -- `body` - The request body, or an empty string if one was not given +- `path` - The path being requested, relative to the root. Will be `/` if not specified +- `query` - A table of key-value pairs representing query parameters in the request path +- `method` - The HTTP method verb, such as `"GET"`, `"POST"`, `"PATCH"`, `"PUT"`, or `"DELETE"`. + Will always be uppercase +- `headers` - A table of key-value pairs representing headers +- `body` - The request body, or an empty string if one was not given --- @@ -220,9 +222,9 @@ Response type for requests in `net.serve`. This is a dictionary that may contain one or more of the following values: -- `status` - The status code for the request, in the range `100` -> `599` -- `headers` - A table of key-value pairs representing headers -- `body` - The response body +- `status` - The status code for the request, in the range `100` -> `599` +- `headers` - A table of key-value pairs representing headers +- `body` - The response body --- @@ -232,12 +234,12 @@ Configuration for `net.serve`. This may contain one of or more of the following values: -- `address` for setting the IP address to serve from. Defaults to the loopback interface - (`http://localhost`). -- `handleRequest` for handling normal http requests, equivalent to just passing a function to - `net.serve` -- `handleWebSocket` for handling web socket requests, which will receive a `WebSocket` object as - its first and only parameter +- `address` for setting the IP address to serve from. Defaults to the loopback interface + (`http://localhost`). +- `handleRequest` for handling normal http requests, equivalent to just passing a function to + `net.serve` +- `handleWebSocket` for handling web socket requests, which will receive a `WebSocket` object as + its first and only parameter When setting `address`, the `handleRequest` callback must also be defined. @@ -270,13 +272,13 @@ The web socket may be in either an "open" or a "closed" state, changing its curr When open: -- Any function on the socket such as `send`, `next` or `close` can be called without erroring -- `next` can be called to yield until the next message is received or the socket becomes closed +- Any function on the socket such as `send`, `next` or `close` can be called without erroring +- `next` can be called to yield until the next message is received or the socket becomes closed When closed: -- `next` will no longer return any message(s) and instead instantly return nil -- `send` will throw an error stating that the socket has been closed +- `next` will no longer return any message(s) and instead instantly return nil +- `send` will throw an error stating that the socket has been closed Once the websocket has been closed, `closeCode` will no longer be nil, and will be populated with a close code according to the diff --git a/content/api-reference/process.md b/src/content/docs/api-reference/process.md similarity index 65% rename from content/api-reference/process.md rename to src/content/docs/api-reference/process.md index bed57bc5..11cea809 100644 --- a/content/api-reference/process.md +++ b/src/content/docs/api-reference/process.md @@ -1,4 +1,6 @@ -# Process +--- +title: Process +--- Built-in functions for the current process & child processes @@ -44,9 +46,9 @@ The current operating system being used. Possible values: -- `"linux"` -- `"macos"` -- `"windows"` +- `"linux"` +- `"macos"` +- `"windows"` --- @@ -58,8 +60,8 @@ The architecture of the processor currently being used. Possible values: -- `"x86_64"` -- `"aarch64"` +- `"x86_64"` +- `"aarch64"` --- @@ -101,11 +103,11 @@ Setting the exit code using this function will override any otherwise automatic #### Parameters -- `code` The exit code to set +- `code` The exit code to set #### Returns -- never +- never --- @@ -121,15 +123,15 @@ process. Refer to the documentation for `SpawnOptions` for specific option keys #### Parameters -- `program` The program to spawn as a child process +- `program` The program to spawn as a child process -- `params` Additional parameters to pass to the program +- `params` Additional parameters to pass to the program -- `options` A dictionary of options for the child process +- `options` A dictionary of options for the child process #### Returns -- A dictionary representing the result of the child process +- A dictionary representing the result of the child process --- @@ -139,13 +141,13 @@ process. Refer to the documentation for `SpawnOptions` for specific option keys A dictionary of options for `process.spawn`, with the following available values: -- `cwd` - The current working directory for the process -- `env` - Extra environment variables to give to the process -- `shell` - Whether to run in a shell or not - set to `true` to run using the default shell, or a - string to run using a specific shell -- `stdio` - How to treat output and error streams from the child process - see - `SpawnOptionsStdioKind` and `SpawnOptionsStdio` for more info -- `stdin` - Optional standard input to pass to spawned child process +- `cwd` - The current working directory for the process +- `env` - Extra environment variables to give to the process +- `shell` - Whether to run in a shell or not - set to `true` to run using the default shell, or a + string to run using a specific shell +- `stdio` - How to treat output and error streams from the child process - see + `SpawnOptionsStdioKind` and `SpawnOptionsStdio` for more info +- `stdin` - Optional standard input to pass to spawned child process --- @@ -155,12 +157,12 @@ Result type for child processes in `process.spawn`. This is a dictionary containing the following values: -- `ok` - If the child process exited successfully or not, meaning the exit code was zero or not - set -- `code` - The exit code set by the child process, or 0 if one was not set -- `stdout` - The full contents written to stdout by the child process, or an empty string if - nothing was written -- `stderr` - The full contents written to stderr by the child process, or an empty string if - nothing was written +- `ok` - If the child process exited successfully or not, meaning the exit code was zero or not + set +- `code` - The exit code set by the child process, or 0 if one was not set +- `stdout` - The full contents written to stdout by the child process, or an empty string if + nothing was written +- `stderr` - The full contents written to stderr by the child process, or an empty string if + nothing was written --- diff --git a/content/api-reference/regex.md b/src/content/docs/api-reference/regex.md similarity index 62% rename from content/api-reference/regex.md rename to src/content/docs/api-reference/regex.md index c84361b8..dc6d338c 100644 --- a/content/api-reference/regex.md +++ b/src/content/docs/api-reference/regex.md @@ -1,4 +1,6 @@ -# Regex +--- +title: Regex +--- Built-in library for regular expressions @@ -33,11 +35,11 @@ This constructor throws an error if the given pattern is invalid. #### Parameters -- `pattern` `string` The string pattern to use +- `pattern` `string` The string pattern to use #### Returns -- `Regex` The new Regex object +- `Regex` The new Regex object --- @@ -52,13 +54,13 @@ matches the pattern. #### Parameters -- `self` Regex +- `self` Regex -- `text` `string` The text to search +- `text` `string` The text to search #### Returns -- `boolean` Whether the text matches the pattern +- `boolean` Whether the text matches the pattern --- @@ -70,13 +72,13 @@ Returns `nil` if no match was found. #### Parameters -- `self` Regex +- `self` Regex -- `text` `string` The text to search +- `text` `string` The text to search #### Returns -- `RegexMatch?` The match object +- `RegexMatch?` The match object --- @@ -88,13 +90,13 @@ Returns `nil` if no matches are found. #### Parameters -- `self` Regex +- `self` Regex -- `text` `string` The text to search +- `text` `string` The text to search #### Returns -- `RegexCaptures?` The captures object +- `RegexCaptures?` The captures object --- @@ -104,13 +106,13 @@ Splits the given text using the regular expression. #### Parameters -- `self` Regex +- `self` Regex -- `text` `string` The text to split +- `text` `string` The text to split #### Returns -- `{ string }` The split text +- `{ string }` The split text --- @@ -120,15 +122,15 @@ Replaces the first match in the given text with the given replacer string. #### Parameters -- `self` Regex +- `self` Regex -- `haystack` `string` The text to search +- `haystack` `string` The text to search -- `replacer` `string` The string to replace matches with +- `replacer` `string` The string to replace matches with #### Returns -- `string` The text with the first match replaced +- `string` The text with the first match replaced --- @@ -138,15 +140,15 @@ Replaces all matches in the given text with the given replacer string. #### Parameters -- `self` Regex +- `self` Regex -- `haystack` `string` The text to search +- `haystack` `string` The text to search -- `replacer` `string` The string to replace matches with +- `replacer` `string` The string to replace matches with #### Returns -- `string` The text with all matches replaced +- `string` The text with all matches replaced --- @@ -162,13 +164,13 @@ Returns the match at the given index, if one exists. #### Parameters -- `self` RegexCaptures +- `self` RegexCaptures -- `index` `number` The index of the match to get +- `index` `number` The index of the match to get #### Returns -- `RegexMatch` The match, if one exists +- `RegexMatch` The match, if one exists --- @@ -178,13 +180,13 @@ Returns the match for the given named match group, if one exists. #### Parameters -- `self` RegexCaptures +- `self` RegexCaptures -- `group` `string` The name of the group to get +- `group` `string` The name of the group to get #### Returns -- `RegexMatch` The match, if one exists +- `RegexMatch` The match, if one exists --- @@ -208,13 +210,13 @@ print(formatted) -- "year=2010, month=03, day=14" #### Parameters -- `self` RegexCaptures +- `self` RegexCaptures -- `format` `string` The format string to use +- `format` `string` The format string to use #### Returns -- `string` The formatted string +- `string` The formatted string --- @@ -224,7 +226,7 @@ A match from a regular expression. Contains the following values: -- `start` -- The start index of the match in the original string. -- `finish` -- The end index of the match in the original string. -- `text` -- The text that was matched. -- `len` -- The length of the text that was matched. +- `start` -- The start index of the match in the original string. +- `finish` -- The end index of the match in the original string. +- `text` -- The text that was matched. +- `len` -- The length of the text that was matched. diff --git a/content/api-reference/roblox.md b/src/content/docs/api-reference/roblox.md similarity index 83% rename from content/api-reference/roblox.md rename to src/content/docs/api-reference/roblox.md index d8cc9c93..7e580eb3 100644 --- a/content/api-reference/roblox.md +++ b/src/content/docs/api-reference/roblox.md @@ -1,4 +1,6 @@ -# Roblox +--- +title: Roblox +--- Built-in library for manipulating Roblox place & model files @@ -44,11 +46,11 @@ local game = roblox.deserializePlace(placeFile) #### Parameters -- `contents` The contents of the place to read +- `contents` The contents of the place to read #### Returns -- DataModel +- DataModel --- @@ -71,11 +73,11 @@ local instances = roblox.deserializeModel(modelFile) #### Parameters -- `contents` The contents of the model to read +- `contents` The contents of the model to read #### Returns -- { Instance } +- { Instance } --- @@ -97,14 +99,14 @@ fs.writeFile("filePath.rbxl", placeFile) #### Parameters -- `dataModel` The DataModel for the place to serialize +- `dataModel` The DataModel for the place to serialize -- `xml` If the place should be serialized as xml or not. Defaults to `false`, meaning the place - gets serialized using the binary format and not xml. +- `xml` If the place should be serialized as xml or not. Defaults to `false`, meaning the place + gets serialized using the binary format and not xml. #### Returns -- string +- string --- @@ -126,14 +128,14 @@ fs.writeFile("filePath.rbxm", modelFile) #### Parameters -- `instances` The array of instances to serialize +- `instances` The array of instances to serialize -- `xml` If the model should be serialized as xml or not. Defaults to `false`, meaning the model - gets serialized using the binary format and not xml. +- `xml` If the model should be serialized as xml or not. Defaults to `false`, meaning the model + gets serialized using the binary format and not xml. #### Returns -- string +- string --- @@ -170,11 +172,11 @@ print("Download link to place: " .. responseLocation) #### Parameters -- `raw` If the cookie should be returned as a pure value or not. Defaults to false +- `raw` If the cookie should be returned as a pure value or not. Defaults to false #### Returns -- string? +- string? --- @@ -208,7 +210,7 @@ end #### Returns -- Database +- Database --- @@ -262,14 +264,14 @@ print(part.CoolProp) --> 13 #### Parameters -- `className` The class to implement the property for. +- `className` The class to implement the property for. -- `propertyName` The name of the property to implement. +- `propertyName` The name of the property to implement. -- `getter` The function which will be called to get the property value when indexed. +- `getter` The function which will be called to get the property value when indexed. -- `setter` The function which will be called to set the property value when indexed. Defaults to a - function that will error with a message saying the property is read-only. +- `setter` The function which will be called to set the property value when indexed. Defaults to a + function that will error with a message saying the property is read-only. --- @@ -304,10 +306,10 @@ part:TestMethod("Hello", "world!") #### Parameters -- `className` The class to implement the method for. +- `className` The class to implement the method for. -- `methodName` The name of the method to implement. +- `methodName` The name of the method to implement. -- `callback` The function which will be called when the method is called. +- `callback` The function which will be called when the method is called. --- diff --git a/content/api-reference/serde.md b/src/content/docs/api-reference/serde.md similarity index 79% rename from content/api-reference/serde.md rename to src/content/docs/api-reference/serde.md index 817e344b..97be624c 100644 --- a/content/api-reference/serde.md +++ b/src/content/docs/api-reference/serde.md @@ -1,10 +1,12 @@ -# Serde +--- +title: Serde +--- Built-in library for: -- serialization & deserialization -- encoding & decoding -- compression +- serialization & deserialization +- encoding & decoding +- compression #### Example usage @@ -33,16 +35,16 @@ See [`EncodeDecodeFormat`] for a list of supported formats. #### Parameters -- `format` The format to use +- `format` The format to use -- `value` The value to encode +- `value` The value to encode -- `pretty` If the encoded string should be human-readable, including things such as newlines and - spaces. Only supported for json and toml formats, and defaults to false +- `pretty` If the encoded string should be human-readable, including things such as newlines and + spaces. Only supported for json and toml formats, and defaults to false #### Returns -- The encoded string +- The encoded string --- @@ -54,13 +56,13 @@ See [`EncodeDecodeFormat`] for a list of supported formats. #### Parameters -- `format` The format to use +- `format` The format to use -- `encoded` The string to decode +- `encoded` The string to decode #### Returns -- The decoded lua value +- The decoded lua value --- @@ -72,13 +74,13 @@ See [`CompressDecompressFormat`] for a list of supported formats. #### Parameters -- `format` The format to use +- `format` The format to use -- `s` The string to compress +- `s` The string to compress #### Returns -- The compressed string +- The compressed string --- @@ -90,13 +92,13 @@ See [`CompressDecompressFormat`] for a list of supported formats. #### Parameters -- `format` The format to use +- `format` The format to use -- `s` The string to decompress +- `s` The string to decompress #### Returns -- The decompressed string +- The decompressed string --- @@ -108,13 +110,13 @@ See [`HashAlgorithm`] for a list of supported algorithms. #### Parameters -- `algorithm` The algorithm to use +- `algorithm` The algorithm to use -- `message` The message to hash +- `message` The message to hash #### Returns -- The hash as a hex string +- The hash as a hex string --- @@ -127,15 +129,15 @@ See [`HashAlgorithm`] for a list of supported algorithms. #### Parameters -- `algorithm` The algorithm to use +- `algorithm` The algorithm to use -- `message` The message to hash +- `message` The message to hash -- `secret` string | buffer +- `secret` string | buffer #### Returns -- The hash as a base64 string +- The hash as a base64 string --- diff --git a/content/api-reference/stdio.md b/src/content/docs/api-reference/stdio.md similarity index 69% rename from content/api-reference/stdio.md rename to src/content/docs/api-reference/stdio.md index f2213071..b3542802 100644 --- a/content/api-reference/stdio.md +++ b/src/content/docs/api-reference/stdio.md @@ -1,4 +1,6 @@ -# Stdio +--- +title: Stdio +--- Built-in standard input / output & utility functions @@ -27,20 +29,20 @@ local input = stdio.readToEnd() Prompts for user input using the wanted kind of prompt: -- `"text"` - Prompts for a plain text string from the user -- `"confirm"` - Prompts the user to confirm with y / n (yes / no) -- `"select"` - Prompts the user to select _one_ value from a list -- `"multiselect"` - Prompts the user to select _one or more_ values from a list -- `nil` - Equivalent to `"text"` with no extra arguments +- `"text"` - Prompts for a plain text string from the user +- `"confirm"` - Prompts the user to confirm with y / n (yes / no) +- `"select"` - Prompts the user to select _one_ value from a list +- `"multiselect"` - Prompts the user to select _one or more_ values from a list +- `nil` - Equivalent to `"text"` with no extra arguments #### Parameters -- `kind` The kind of prompt to use +- `kind` The kind of prompt to use -- `message` The message to show the user +- `message` The message to show the user -- `defaultOrOptions` The default value for the prompt, or options to choose from for selection - prompts +- `defaultOrOptions` The default value for the prompt, or options to choose from for selection + prompts --- @@ -61,11 +63,11 @@ print("This text will be normal") #### Parameters -- `color` The color to use +- `color` The color to use #### Returns -- A printable ANSI string +- A printable ANSI string --- @@ -86,11 +88,11 @@ print("This text will be normal") #### Parameters -- `style` The style to use +- `style` The style to use #### Returns -- A printable ANSI string +- A printable ANSI string --- @@ -100,11 +102,11 @@ Formats arguments into a human-readable string with syntax highlighting for tabl #### Parameters -- `...` The values to format +- `...` The values to format #### Returns -- The formatted string +- The formatted string --- @@ -114,7 +116,7 @@ Writes a string directly to stdout, without any newline. #### Parameters -- `s` The string to write to stdout +- `s` The string to write to stdout --- @@ -124,7 +126,7 @@ Writes a string directly to stderr, without any newline. #### Parameters -- `s` The string to write to stderr +- `s` The string to write to stderr --- @@ -134,6 +136,6 @@ Reads the entire input from stdin. #### Returns -- The input from stdin +- The input from stdin --- diff --git a/content/api-reference/task.md b/src/content/docs/api-reference/task.md similarity index 74% rename from content/api-reference/task.md rename to src/content/docs/api-reference/task.md index 48b76c1d..87e12803 100644 --- a/content/api-reference/task.md +++ b/src/content/docs/api-reference/task.md @@ -1,4 +1,6 @@ -# Task +--- +title: Task +--- Built-in task scheduler & thread spawning @@ -34,7 +36,7 @@ Stops a currently scheduled thread from resuming. #### Parameters -- `thread` The thread to cancel +- `thread` The thread to cancel --- @@ -44,13 +46,13 @@ Defers a thread or function to run at the end of the current task queue. #### Parameters -- `functionOrThread` The function or thread to defer +- `functionOrThread` The function or thread to defer -- `...` T... +- `...` T... #### Returns -- The thread that will be deferred +- The thread that will be deferred --- @@ -60,15 +62,15 @@ Delays a thread or function to run after `duration` seconds. #### Parameters -- `duration` number +- `duration` number -- `functionOrThread` The function or thread to delay +- `functionOrThread` The function or thread to delay -- `...` T... +- `...` T... #### Returns -- The thread that will be delayed +- The thread that will be delayed --- @@ -81,13 +83,13 @@ run in the background. #### Parameters -- `functionOrThread` The function or thread to spawn +- `functionOrThread` The function or thread to spawn -- `...` T... +- `...` T... #### Returns -- The thread that was spawned +- The thread that was spawned --- @@ -101,10 +103,10 @@ less. #### Parameters -- `duration` The amount of time to wait +- `duration` The amount of time to wait #### Returns -- The exact amount of time waited +- The exact amount of time waited --- diff --git a/content/getting-started/1-installation.mdx b/src/content/docs/getting-started/1-installation.mdx similarity index 76% rename from content/getting-started/1-installation.mdx rename to src/content/docs/getting-started/1-installation.mdx index 715dd9ce..28618167 100644 --- a/content/getting-started/1-installation.mdx +++ b/src/content/docs/getting-started/1-installation.mdx @@ -1,6 +1,8 @@ -import { Callout, Steps } from "nextra/components"; +--- +title: Installation +--- -# Installation +import { Aside, Steps } from "@astrojs/starlight/components"; The preferred way of installing Lune is using [Rokit](https://github.com/rojo-rbx/rokit), a toolchain manager for Roblox projects. Rokit can manage your installed version of Lune and @@ -8,26 +10,26 @@ other ecosystem tools, and allows you to easily upgrade to newer versions as the -### Installing Rokit +1. ### Installing Rokit -Follow the installation instructions on the [Rokit](https://github.com/rojo-rbx/rokit) page. + Follow the installation instructions on the [Rokit](https://github.com/rojo-rbx/rokit) page. -### Installing Lune +2. ### Installing Lune -Navigate to your project directory using your terminal, and run the following command: + Navigate to your project directory using your terminal, and run the following command: -```sh copy filename="Bash" -rokit add lune -``` + ```bash title="Terminal" + rokit add lune + ``` -### Upgrading Lune +3. ### Upgrading Lune -When a new version of Lune becomes available, using Rokit will also allow you to easily upgrade to it. -Navigate to your project directory using your terminal again, and run the following command: + When a new version of Lune becomes available, using Rokit will also allow you to easily upgrade to it. + Navigate to your project directory using your terminal again, and run the following command: -```sh copy filename="Bash" -rokit update lune -``` + ```bash title="Terminal" + rokit update lune + ``` @@ -55,7 +57,7 @@ and [Aftman](https://github.com/LPGhatguy/aftman). Windows users can use [Scoop](https://scoop.sh) to install Lune. -```ps copy filename="PowerShell" +```sh filename="PowerShell" # Add the bucket scoop bucket add lune https://github.com/CompeyDev/lune-packaging.git @@ -67,14 +69,14 @@ scoop install lune macOS and Linux users can use [Homebrew](https://brew.sh) to install Lune. -```sh copy filename="Bash" +```bash title="Terminal" # Installs latest stable precompiled binary brew install lune ``` **_or_** -```sh copy filename="Bash" +```bash title="Terminal" # Builds from latest stable source brew install lune --build-from-source ``` @@ -84,10 +86,10 @@ brew install lune --build-from-source APT is a package manager for Debian-based Linux distributions that uses `dpkg` to install packages.
Follow the instructions at the unofficial [lune-packaging](https://github.com/CompeyDev/lune-packaging#apt) repository to install Lune using APT. - + ### AppImage @@ -104,42 +106,42 @@ There are a number of packages available on the AUR: These can be installed with your preferred AUR package manager as such: -```sh copy filename="Bash" +```bash title="Terminal" paru -S [PACKAGE_NAME] ``` **_or_** -```sh copy filename="Bash" +```bash title="Terminal" yay -S [PACKAGE_NAME] ``` - + ### Nix macOS\* and Linux users can use [Nix](https://nixos.org/) to install Lune. - +
Imperatively
**NixOS** -```sh copy filename="Bash" +```bash title="Terminal" nix-env -iA nixos.lune ``` **Non NixOS** -```sh copy filename="Bash" +```bash title="Terminal" nix-env -iA nixpkgs.lune # If you are using flakes nix profile install nixpkgs#lune @@ -152,7 +154,7 @@ nix profile install nixpkgs#lune
**With [home-manager](https://github.com/nix-community/home-manager)** -```nix copy filename="nix" +```nix title="Terminal" home.packages = with pkgs; [ lune ]; @@ -160,7 +162,7 @@ home.packages = with pkgs; [ **system-wide NixOS configuration** -```nix copy filename="nix" +```nix title="Terminal" enviroment.systemPackages = with pkgs; [ lune ]; @@ -173,7 +175,7 @@ enviroment.systemPackages = with pkgs; [
You can temporarily use Lune in your shell. You can use this to try out Lune before deciding to permanently install it. -```sh copy filename="Bash" +```bash title="Terminal" nix-shell -p lune ``` @@ -190,7 +192,7 @@ Building and installing from source requires the latest version of [Rust & Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to be installed on your system.
Once installed, run the following command in your terminal: -```sh copy filename="Bash" +```bash title="Terminal" cargo install lune --locked ``` @@ -201,7 +203,7 @@ compiling from source unlike `cargo install`. Lune is packaged in a `binstall` c With `binstall` installed and in your path, run: -```sh copy filename="Bash" +```bash title="Terminal" cargo binstall lune ``` @@ -211,7 +213,7 @@ cargo binstall lune Congratulations! You've installed Lune and are now ready to write your first script. -- If you want to write standalone scripts, head over to the - [Introduction](./2-introduction/1-hello-lune.md) section. -- If you want to write Lune scripts specifically for Roblox, check out the - [Roblox](../roblox/1-introduction.md) section. +A great place to continue reading is the [Lune Book](../../the-book/1-hello-lune), which is also part +of the official Lune documentation, and will give you a guided and comprehensive introduction to Lune. + +Or, if you want to dive right into specific resources, check out the API reference in the sidebar. diff --git a/content/getting-started/3-command-line-usage.md b/src/content/docs/getting-started/2-command-line-usage.md similarity index 73% rename from content/getting-started/3-command-line-usage.md rename to src/content/docs/getting-started/2-command-line-usage.md index 3bddf873..67c9353e 100644 --- a/content/getting-started/3-command-line-usage.md +++ b/src/content/docs/getting-started/2-command-line-usage.md @@ -1,24 +1,26 @@ -# Command-Line Usage +--- +title: Command-Line Usage +--- ## Running Scripts When you've written a script file, for example `script-name.luau`, you can run it as such: -```sh copy +```bash title="Terminal" lune run script-name ``` This will look for the file `script-name.luau`**_[1]_** in a few locations: -- The current directory -- The folder `lune` in the current directory, if it exists -- The folder `.lune` in the current directory, if it exists -- The folder `lune` in the _home_ directory, if it exists -- The folder `.lune` in the _home_ directory, if it exists +- The current directory +- The folder `lune` in the current directory, if it exists +- The folder `.lune` in the current directory, if it exists +- The folder `lune` in the _home_ directory, if it exists +- The folder `.lune` in the _home_ directory, if it exists ## Listing Scripts -```sh copy +```bash title="Terminal" lune list ``` @@ -28,14 +30,14 @@ lua-style comment arrow (`-->`). ## Advanced Usage -```sh copy +```bash title="Terminal" lune run - ``` Runs a script passed to Lune using stdin. Useful for running scripts piped to Lune from external sources. Example: -```sh copy +```bash title="Terminal" echo "print 'Hello, terminal!'" | lune run - ``` diff --git a/content/getting-started/4-editor-setup.md b/src/content/docs/getting-started/3-editor-setup.md similarity index 93% rename from content/getting-started/4-editor-setup.md rename to src/content/docs/getting-started/3-editor-setup.md index ca845066..48fdb688 100644 --- a/content/getting-started/4-editor-setup.md +++ b/src/content/docs/getting-started/3-editor-setup.md @@ -1,4 +1,6 @@ -# Editor Setup +--- +title: Editor Setup +--- Lune prioritizes developer experience, and as such type definitions and documentation are provided for several editors and tools without any additional downloads. This guide will help you get set up @@ -12,6 +14,6 @@ is currently the main language server providing editor support for Luau. It supp Once you have installed the language server, as well as Lune, running the following built-in command will generate type definition files, and add / modify a standardized `.luaurc` configuration file pointing to them: -```sh +```bash title="Terminal" lune setup ``` diff --git a/src/content/docs/getting-started/4-security.mdx b/src/content/docs/getting-started/4-security.mdx new file mode 100644 index 00000000..4b8e06e4 --- /dev/null +++ b/src/content/docs/getting-started/4-security.mdx @@ -0,0 +1,39 @@ +--- +title: Security +--- + +import { Steps } from "@astrojs/starlight/components"; + +When running Lune scripts, it is important to note that any scripts you execute have +full access to your device - this means access to your files, programs, and more. +It is important to stay cautious when executing a script from a source you don't trust. + +Some alternatives to solving this problem are: + +1. Running Lune scripts in a custom sandboxed environment. +2. Using a containerized environment such as Docker. +3. Using a virtual machine. + +## Sandboxing + +Lune provides a rudimentary, albeit working sandboxing example. We provide steps to use it here, +but for proper security & deployments, using a container or a virtual machine is highly recommended. + + + +1. Copy the [sandbox module](https://github.com/lune-org/docs/blob/main/modules/sandbox.luau) and place it in a file named `sandbox.luau`. + +2. Now, place the untrusted script you want to run safely next to the `sandbox.luau` script. + + ```bash title="Terminal" + lune run sandbox.luau script.luau -- [ARGUMENTS_HERE] + ``` + + Replace `script.luau` and `[ARGUMENTS_HERE]` with the path to the script and the arguments to run it with. + +3. As the script runs, any requires to potentially dangerous modules will require your approval + before continuing and any invocations to methods within approved modules will be logged. + + Additionally, the output of the sandbox script and the script being run will be separated. + + diff --git a/content/index.md b/src/content/docs/index.md similarity index 91% rename from content/index.md rename to src/content/docs/index.md index 5eff56e1..1f1fe035 100644 --- a/content/index.md +++ b/src/content/docs/index.md @@ -1,4 +1,7 @@ -# Lune +--- +title: Lune +description: Get started with writing Luau using the Lune runtime. +--- A standalone [Luau](https://luau-lang.org) runtime. @@ -21,4 +24,4 @@ Lune provides fully asynchronous APIs wherever possible, and is built in Rust ## Where do I start? -Head over to the [Installation](./getting-started/1-installation.md) page to get started using Lune! +Head over to the [Installation](./getting-started/1-installation) page to get started using Lune! diff --git a/content/roblox/1-introduction.md b/src/content/docs/roblox/1-introduction.md similarity index 87% rename from content/roblox/1-introduction.md rename to src/content/docs/roblox/1-introduction.md index 70528a36..cc629319 100644 --- a/content/roblox/1-introduction.md +++ b/src/content/docs/roblox/1-introduction.md @@ -1,7 +1,6 @@ - - - -# The `roblox` Library +--- +title: "The Roblox Library" +--- Lune has a powerful built-in library and set of APIs for manipulating Roblox place files and model files. It contains APIs for reading & writing files, and gives you instances to use, just as if you diff --git a/content/roblox/2-examples.md b/src/content/docs/roblox/2-examples.md similarity index 96% rename from content/roblox/2-examples.md rename to src/content/docs/roblox/2-examples.md index 79ed0389..b8efcd89 100644 --- a/content/roblox/2-examples.md +++ b/src/content/docs/roblox/2-examples.md @@ -1,7 +1,6 @@ - - - -# Example Scripts +--- +title: "Example Scripts" +--- These are a few short examples of things you can do using the built-in `roblox` library. diff --git a/src/content/docs/roblox/3-remodel-migration.mdx b/src/content/docs/roblox/3-remodel-migration.mdx new file mode 100644 index 00000000..587c12b3 --- /dev/null +++ b/src/content/docs/roblox/3-remodel-migration.mdx @@ -0,0 +1,124 @@ +--- +title: "Migrating from Remodel" +--- + +import { Steps } from "@astrojs/starlight/components"; + +If you have used [Remodel](https://github.com/rojo-rbx/remodel) before to manipulate place and/or +model files, this migration guide will help you get started with accomplishing the same tasks in +Lune. + +## Drop-in Compatibility + +This guide provides a module which translates all of the relevant Lune APIs to their Remodel +equivalents. For more details or manual migration steps, check out +[Differences Between Lune & Remodel](#differences-between-lune--remodel) below. + + + +1. Copy the [remodel module](https://github.com/lune-org/docs/blob/main/modules/remodel.luau) and place it in a file named `remodel.luau`. + + This module is quite large, but you will not need to read through it unless you want to know about + the internal details of how Remodel used to work. + +2. Next, create another script next to your `remodel.luau`. We will be naming it `example.luau`, but + you can name it whatever you want. This example code is from one of the legacy Remodel-native + example scripts, with only the top line added: + + ```luau + // remodel.luau + local remodel = require("./remodel") + + -- One use for Remodel is to move the terrain of one place into another place. + local inputGame = remodel.readPlaceFile("input-place.rbxlx") + local outputGame = remodel.readPlaceFile("output-place.rbxlx") + + -- This isn't possible inside Roblox, but works just fine in Remodel! + outputGame.Workspace.Terrain:Destroy() + inputGame.Workspace.Terrain.Parent = outputGame.Workspace + + remodel.writePlaceFile("output-place-updated.rbxlx", outputGame) + ``` + +3. Finally, run the script you've created by providing the script name to Lune, in our case `example`, + without the luau file extension. Everything should work the same way it did when running natively in + Remodel, now running in Lune 🚀 + + ```bash title="Terminal" + lune run example + ``` + + + +## Differences Between Lune & Remodel + +Most APIs previously found in Remodel have direct equivalents in Lune, below are some direct links +to APIs that are equivalent or very similar. + +
+Places & Models + +- `remodel.readPlaceFile` ➡ [`fs.readFile`](../api-reference/fs.md#readfile) & + [`roblox.deserializePlace`](../api-reference/roblox.md#deserializeplace) +- `remodel.readModelFile` ➡ [`fs.readFile`](../api-reference/fs.md#readfile) & + [`roblox.deserializeModel`](../api-reference/roblox.md#deserializemodel) +- `remodel.readPlaceAsset` ➡ [`net.request`](../api-reference/net.md#request) & + [`roblox.deserializePlace`](../api-reference/roblox.md#deserializeplace) +- `remodel.readModelAsset` ➡ [`net.request`](../api-reference/net.md#request) & + [`roblox.deserializeModel`](../api-reference/roblox.md#deserializemodel) +- `remodel.writePlaceFile` ➡ [`roblox.serializePlace`](../api-reference/roblox.md#serializeplace) + & [`fs.writeFile`](../api-reference/fs.md#writefile) +- `remodel.writeModelFile` ➡ [`roblox.serializeModel`](../api-reference/roblox.md#serializemodel) + & [`fs.writeFile`](../api-reference/fs.md#writefile) +- `remodel.writeExistingPlaceAsset` ➡ + [`roblox.serializePlace`](../api-reference/roblox.md#serializeplace) & + [`net.request`](../api-reference/net.md#request) +- `remodel.writeExistingModelAsset` ➡ + [`roblox.serializeModel`](../api-reference/roblox.md#serializemodel) & + [`net.request`](../api-reference/net.md#request) +- `remodel.getRawProperty` ➡ no equivalent, you can get properties directly by indexing +- `remodel.setRawProperty` ➡ no equivalent, you can set properties directly by indexing + +
+ +
+Files & Directories + +- `remodel.readFile` ➡ [`fs.readFile`](../api-reference/fs.md#readfile) +- `remodel.readDir` ➡ [`fs.readDir`](../api-reference/fs.md#readdir) +- `remodel.writeFile` ➡ [`fs.writeFile`](../api-reference/fs.md#writefile) +- `remodel.createDirAll` ➡ [`fs.writeDir`](../api-reference/fs.md#writedir) +- `remodel.removeFile` ➡ [`fs.removeFile`](../api-reference/fs.md#removefile) +- `remodel.removeDir` ➡ [`fs.removeDir`](../api-reference/fs.md#removedir) +- `remodel.isFile` ➡ [`fs.isFile`](../api-reference/fs.md#isfile) +- `remodel.isDir` ➡ [`fs.isDir`](../api-reference/fs.md#isdir) + +
+ +
+JSON + +- `json.fromString` ➡ [`serde.decode`](../api-reference/serde.md#decode) +- `json.toString` ➡ [`serde.encode`](../api-reference/serde.md#encode) +- `json.toStringPretty` ➡ [`serde.encode`](../api-reference/serde.md#encode) + +
+ +Since Lune is meant to be a general-purpose Luau runtime, there are also some more general +differences, and Lune takes a different approach from Remodel in certain areas: + +- Lune runs Luau instead of Lua 5.3. +- APIs are more loosely coupled, meaning that a task may require more steps using Lune. This also + means that Lune is more flexible and supports more use cases. +- Built-in libraries are not accessible from global variables, you have to explicitly import them + using `require("@lune/library-name")`. +- Arguments given to scripts are not available in `...`, you have to use + [`process.args`](../api-reference/process.md#args) instead. +- Lune generally supports all of the Roblox datatypes that are gettable/settable on instance + properties. For a full list of available datatypes, check out the + [API Status](./4-api-status.md) page. + +--- + +There may be more differences than are listed here, and the Lune-specific guides and examples may +provide more info, but this should be all you need to know to migrate from Remodel. Good luck! diff --git a/content/roblox/4-api-status.md b/src/content/docs/roblox/4-api-status.md similarity index 98% rename from content/roblox/4-api-status.md rename to src/content/docs/roblox/4-api-status.md index c100369b..e93aa8ae 100644 --- a/content/roblox/4-api-status.md +++ b/src/content/docs/roblox/4-api-status.md @@ -1,7 +1,6 @@ - - - -# API Status +--- +title: API Status +--- This is a page indicating the current implementation status for instance methods and datatypes in the `roblox` library. diff --git a/src/content/docs/the-book/1-hello-lune.md b/src/content/docs/the-book/1-hello-lune.md new file mode 100644 index 00000000..1e30993a --- /dev/null +++ b/src/content/docs/the-book/1-hello-lune.md @@ -0,0 +1,23 @@ +--- +title: Hello, Lune! +--- + +Congratulations! Lune is now set up and you are ready to start writing scripts 🎉 + +If you've already written some kind of Lua (or Luau) script before, the examples provided in the +overview below should make you feel right at home. They are organized in order of least complex to +most complex, and you don't really have to read them all to understand how Lune works, though it may +help you out. Good luck! + +## Overview + +1. [Hello, Lune!](./1-hello-lune.md) (you are here) +2. [Built-in Libraries](./2-built-in-libraries.md) +3. [Standard I/O](./3-standard-io.mdx) +4. [Script Arguments](./4-script-arguments.md) +5. [Network Requests](./5-network-requests.mdx) +6. [Files & Directories](./6-files-and-directories.mdx) +7. [Environment Variables](./7-environment-variables.md) +8. [Modules](./8-modules.mdx) +9. [Task Scheduler](./9-task-scheduler.mdx) +10. [Spawning Processes](./10-spawning-processes.md) diff --git a/content/getting-started/2-introduction/10-spawning-processes.md b/src/content/docs/the-book/10-spawning-processes.md similarity index 87% rename from content/getting-started/2-introduction/10-spawning-processes.md rename to src/content/docs/the-book/10-spawning-processes.md index ac961756..a22c7d05 100644 --- a/content/getting-started/2-introduction/10-spawning-processes.md +++ b/src/content/docs/the-book/10-spawning-processes.md @@ -1,6 +1,8 @@ -# Spawning Processes +--- +title: Spawning Processes +--- -Whenever Lune does not have the API you need as part of its built-in libraries, or when you want to +Whenever Lune does not have the API you need as part of its standard libraries, or when you want to use a program that already exists but interact with it from within Lune, you can use [`process.exec`](../../api-reference/process.md#exec). @@ -10,7 +12,7 @@ This example calls out to the native "ping" program found in many operating syst output into something more usable to us. This may look scary with lots of weird symbols, but, it's just some Lua-style pattern matching to -parse the lines of "min/avg/max/stddev = W/X/Y/Z ms" that the ping program gives back to us. +parse the lines of `"min/avg/max/stddev = W/X/Y/Z ms"` that the ping program gives back to us. ```luau copy print("Sending 4 pings to google 🌏") diff --git a/content/getting-started/2-introduction/2-built-in-libraries.md b/src/content/docs/the-book/2-built-in-libraries.md similarity index 71% rename from content/getting-started/2-introduction/2-built-in-libraries.md rename to src/content/docs/the-book/2-built-in-libraries.md index 1cec4d0e..78016de1 100644 --- a/content/getting-started/2-introduction/2-built-in-libraries.md +++ b/src/content/docs/the-book/2-built-in-libraries.md @@ -1,12 +1,13 @@ -# Built-in Libraries +--- +title: The Standard Library +--- -Lune contains a large set of built-in libraries, much like Luau itself. These libraries include, but -are not limited to, these libraries and their common use cases: +Lune contains a comprehensive standard library. It includes, but +is not limited to, these libraries and their common use cases: - The [`fs`](../../api-reference/fs.md) library for manipulating files - The [`net`](../../api-reference/net.md) library for making HTTP requests -- The [`process`](../../api-reference/process.md) library for executing external programs and - processes +- The [`process`](../../api-reference/process.md) library for executing external programs and processes This is just a small subset of what is available in Lune, but for now, what is important is that these libraries must be imported using a special kind of `require` statement: @@ -20,8 +21,8 @@ local process = require("@lune/process") As you can see above, unlike Luau's standard libraries such as [`math`](https://luau-lang.org/library#math-library), [`table`](https://luau-lang.org/library#table-library), -[`string`](https://luau-lang.org/library#string-library), and others, Lune's built-in libraries are -not available as global variables and importing them before using them is required (pun intended). +[`string`](https://luau-lang.org/library#string-library), and others, Lune's built-in libraries +are not available as global variables, and importing them before using them is, _required_. The next few sections will contain examples of how to run scripts, more specific usage of Lune's built-in libraries, and what they are most commonly used for. diff --git a/content/getting-started/2-introduction/3-standard-io.mdx b/src/content/docs/the-book/3-standard-io.mdx similarity index 93% rename from content/getting-started/2-introduction/3-standard-io.mdx rename to src/content/docs/the-book/3-standard-io.mdx index dd03c86e..3c96f164 100644 --- a/content/getting-started/2-introduction/3-standard-io.mdx +++ b/src/content/docs/the-book/3-standard-io.mdx @@ -1,4 +1,6 @@ -# Standard I/O +--- +title: Standard I/O +--- One of Lune's most useful libraries for writing scripts is the standard I/O library, also known as `stdio`, which will be the first one we introduce here. The pages following this one will introduce @@ -10,7 +12,8 @@ The easiest way to get started and being productive using Lune is to prompt the script for some text input, which you can do using the [`stdio`](../../api-reference/stdio.md) library. Let's make a script called `hello.luau`: -```luau copy filename="hello.luau" +```luau +// hello.luau local stdio = require("@lune/stdio") local name = stdio.prompt("text", "Hello there! What's your name?") @@ -20,14 +23,15 @@ print("Hello, " .. name .. "!") Now you can place this script in your current directory, and run it using Lune: -```sh copy filename="Bash" +```bash title="Terminal" lune run hello ``` You can also prompt for more than just text. Let's extend the above script and ask the person running the script if that was really their name: -```luau copy filename="hello.luau" +```luau +// hello.luau local confirmed = stdio.prompt("confirm", "Is that really your name?") if confirmed then print("Nice to meet you, " .. name .. "!") @@ -54,7 +58,8 @@ Here's a tiny game you can play versus the computer, using nothing but Lune's script, but don't worry, it is still only using the same functions as the script above, albeit this time together with a `while ... do` loop and a couple `if ... then` statements: -```luau copy filename="guessing-game.luau" +```luau +// guessing-game.luau local stdio = require("@lune/stdio") print("") @@ -85,7 +90,7 @@ print("") Just like before, you can place this script in your current directory, and run it using Lune: -```sh copy filename="Bash" +```sh title="Terminal" lune run guessing-game ``` diff --git a/content/getting-started/2-introduction/4-script-arguments.md b/src/content/docs/the-book/4-script-arguments.md similarity index 93% rename from content/getting-started/2-introduction/4-script-arguments.md rename to src/content/docs/the-book/4-script-arguments.md index 339e12f2..5e1e78e4 100644 --- a/content/getting-started/2-introduction/4-script-arguments.md +++ b/src/content/docs/the-book/4-script-arguments.md @@ -1,8 +1,10 @@ -# Script Arguments +--- +title: Script Arguments +--- Arguments can be passed to Lune scripts directly from the command line when running them: -```sh copy filename="Bash" +```bash title="Terminal" lune run script-name arg1 arg2 "argument three" ``` @@ -10,7 +12,7 @@ These arguments will then be available in your script using the [process](../../api-reference/process.md) built-in library, more specifically in [`process.args`](../../api-reference/process.md#args): -```luau copy +```luau local process = require("@lune/process") print(process.args) @@ -23,7 +25,7 @@ Arguments in [`process.args`](../../api-reference/process.md#args) will always b contiguous array, and are guaranteed to not change during runtime. A useful pattern here could be to check for arguments given, and if there are none, prompt the user for input: -```luau copy +```luau local process = require("@lune/process") local stdio = require("@lune/stdio") diff --git a/content/getting-started/2-introduction/5-network-requests.mdx b/src/content/docs/the-book/5-network-requests.mdx similarity index 99% rename from content/getting-started/2-introduction/5-network-requests.mdx rename to src/content/docs/the-book/5-network-requests.mdx index aa5b0a8e..ab770f3b 100644 --- a/content/getting-started/2-introduction/5-network-requests.mdx +++ b/src/content/docs/the-book/5-network-requests.mdx @@ -1,4 +1,6 @@ -# Network Requests +--- +title: Network Requests +--- One of Lune's most useful libraries is the networking library, also known as `net`. This library lets you access the internet and make HTTP requests to different websites, servers, and external diff --git a/content/getting-started/2-introduction/6-files-and-directories.mdx b/src/content/docs/the-book/6-files-and-directories.mdx similarity index 74% rename from content/getting-started/2-introduction/6-files-and-directories.mdx rename to src/content/docs/the-book/6-files-and-directories.mdx index 9d354755..27241349 100644 --- a/content/getting-started/2-introduction/6-files-and-directories.mdx +++ b/src/content/docs/the-book/6-files-and-directories.mdx @@ -1,6 +1,8 @@ -import { FileTree, Tabs, Tab } from "nextra/components"; +--- +title: Files & Directories +--- -# Files & Directories +import { FileTree, Tabs, TabItem } from "@astrojs/starlight/components"; Lune has a built-in library for interacting with the filesystem, [`fs`](../../api-reference/fs.md). This library will let you read, write, move, copy files & directories, and more. @@ -10,40 +12,39 @@ This library will let you read, write, move, copy files & directories, and more. Let's use this directory & file tree structure for our examples: - - - - - - - - - + +- files.luau +- dirs.luau +- hello-world.json +- files + - coolstuff.toml + - super.secret.txt +
Show file contents - - ```json copy filename="hello-world.json" + + ```json title="JSON" { "Hello": "World" } ``` - - - ```toml copy filename="coolstuff.toml" + + + ```toml title="TOML" [you] cool = true awesome = "yep" ``` - - - ```txt copy filename="super.secret.txt" + + + ```txt title="TXT" Hey you're not supposed to be in here! ``` - +
@@ -52,7 +53,8 @@ Let's use this directory & file tree structure for our examples: Reading and writing files using the `fs` library is very simple and _only_ involves strings: -```luau copy filename="files.luau" +```luau +// files.luau local fs = require("@lune/fs") --> Print out the contents of all of the files @@ -78,7 +80,8 @@ It is up to you to know how your files are structured and handle them appropriat Reading and creating directories has a very similar API, but slightly different parameters and return values: -```luau copy filename="dirs.luau" +```luau +// dirs.luau local fs = require("@lune/fs") --[[ @@ -113,17 +116,17 @@ In the above example: - `fs.readDir` returns a table (array) of strings, with file and directory names - `fs.writeDir` takes only the directory name (path) to create a directory at -- `fs.removeDir` removes the directory **_and everything inside it_**, use with caution +- `fs.removeDir` removes the directory **_and everything inside it_** - use with caution! ## Resulting File Tree This is what our directory & file tree structure would look like after running the above examples: - - - - - - + +- files.luau +- dirs.luau +- hello-world.json +- myCoolDir/ + diff --git a/content/getting-started/2-introduction/7-environment-variables.md b/src/content/docs/the-book/7-environment-variables.md similarity index 95% rename from content/getting-started/2-introduction/7-environment-variables.md rename to src/content/docs/the-book/7-environment-variables.md index 8d0a34f1..d7e85b6a 100644 --- a/content/getting-started/2-introduction/7-environment-variables.md +++ b/src/content/docs/the-book/7-environment-variables.md @@ -1,10 +1,12 @@ -# Environment Variables +--- +title: Environment Variables +--- Environment variables, just like script arguments, are available using the [process](../../api-reference/process.md) built-in library, more specifically in [`process.env`](../../api-reference/process.md#env): -```luau copy +```luau local process = require("@lune/process") assert(process.env.PATH ~= nil, "Missing PATH") @@ -23,7 +25,7 @@ You can also iterate over all of the known environment variables using Luau's ge Here is an example snippet that prints a checkmark if an environment variable has some contents and is not empty, and a red cross otherwise: -```luau copy +```luau local process = require("@lune/process") for key, value in process.env do diff --git a/src/content/docs/the-book/8-modules.mdx b/src/content/docs/the-book/8-modules.mdx new file mode 100644 index 00000000..f3e6c96f --- /dev/null +++ b/src/content/docs/the-book/8-modules.mdx @@ -0,0 +1,89 @@ +--- +title: Modules +--- + +import { FileTree, Tabs, TabItem, Aside } from "@astrojs/starlight/components"; + +At this point you know how the most important built-in libraries in Lune work and how to use them, +and your code is probably getting longer and more difficult to read. Splitting your code into +multiple files can help you stay organized. + +Modularizing your code and splitting it across several files in Lune is different from other +versions of Lua and Luau, and more similar to how things work in other languages such as JavaScript. + +## Example File Tree + +Let's use this directory & file tree structure for our examples: + + + +- main.luau +- sibling.luau +- modules + - init.luau + - module.luau + + + + + + ```luau + // main.luau + local sibling = require("sibling") + local modules = require("modules") + + print(sibling.Hello) --> World + + print(modules.Child.Foo) --> Bar + print(modules.Child.Fizz) --> Buzz + + print(modules.Sibling.Hello) --> World + ``` + + + ```luau + // sibling.luau + return { + Hello = "World", + } + ``` + + + ```luau + // modules/init.luau + return { + Child = require("@self/child"), + Sibling = require("./sibling"), + } + ``` + + + ```luau + // modules/child.luau + return { + Foo = "Bar", + Fizz = "Buzz", + } + ``` + + + + +## File Require Statements + +Let's decipher these modules and what they are doing: + +- The `main` module requires `sibling` and `modules` next to it +- The `modules` module requires `child` inside of it using the special `@self` alias +- The `modules` module requires `sibling` next to it using `./` + +This is the standard behavior according to Luau require-by-string, +which you can read more about on the official Luau documentation site. + + diff --git a/content/getting-started/2-introduction/9-task-scheduler.mdx b/src/content/docs/the-book/9-task-scheduler.md similarity index 65% rename from content/getting-started/2-introduction/9-task-scheduler.mdx rename to src/content/docs/the-book/9-task-scheduler.md index 7de25f5b..3e8a5cd2 100644 --- a/content/getting-started/2-introduction/9-task-scheduler.mdx +++ b/src/content/docs/the-book/9-task-scheduler.md @@ -1,14 +1,42 @@ -# The Task Scheduler +--- +title: The Task Scheduler +--- Lune has a built-in task scheduler, which can let you run things at fixed intervals, ensure some work happens after everything else is already done, and more. -## Spawning Tasks & Waiting +The task scheduler is the backbone of Lune, and lets you handle structured concurrency. It is +implemented using lightweight Lua threads / coroutines, and has **strong ordering guarantees**. + +## Ordering + +The main purpose of the task scheduler is to ensure consistent ordering, and to +let you prioritize work on three different levels by using the `task` standard library: + +1. **Immediate**: Tasks that should run immediately can be spawned using `task.spawn`. +2. **Deferred**: Tasks that should run after all immediate tasks have finished can be spawned using `task.defer`. +3. **Delayed**: Tasks that should run after a certain amount of time has passed can be spawned using `task.delay`. + +
+Advanced: Runtime-Controlled Threads & Prioritization + +These are user-facing concepts, but perhaps more interesting, is that Lune _**prioritizes Lua threads**_ +over runtime-spawned tasks, such as those for incoming requests in `net.serve`. + +This means that, in real world scenarios such as handling incoming requests in an HTTP server, the scheduler +will ensure that your existing tasks are not starved of resources, and are always prioritized over handling +new requests, for maximum throughput & lowest possible latency. + +
+ +## Example Usage + +### Spawning Tasks & Waiting This example script will run several tasks concurrently, in lightweight Lua threads, also known as coroutines: -```luau copy +```luau local task = require("@lune/task") print("Hello, scheduler!") @@ -30,12 +58,12 @@ task.delay(5, function() end) ``` -## Deferring Work +### Deferring Work This example script runs a bit of work after all other threads have finished their work or are yielding waiting for some other result: -```luau copy +```luau local task = require("@lune/task") task.defer(function() @@ -55,12 +83,12 @@ end print("Done!") ``` -## Advanced Usage & Async +### Advanced Usage & Async -Spawning tasks like this can be very useful together with asynchronous APIs from other built-in +Spawning tasks like this can be very useful together with asynchronous APIs from other standard libraries, such as [`net.request`](../../api-reference/net.md#request): -```luau copy +```luau local net = require("@lune/net") local task = require("@lune/task") @@ -83,13 +111,13 @@ completed = true
Bonus -## Barebones Signal Implementation +### Barebones Signal Implementation Using the task library, it becomes trivial to implement signal objects that take callbacks to run when a signal is fired, and that can handle both synchronous and yielding (async) callbacks without additional complexity: -```luau copy +```luau local task = require("@lune/task") local function newSignal() diff --git a/tsconfig.json b/tsconfig.json index f2c1ba36..8bf91d3b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,25 +1,5 @@ { - "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": false, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "incremental": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "plugins": [ - { - "name": "next" - } - ] - }, - "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] }