@thigasdevelopment/luam 0.13.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,137 +18,69 @@
18
18
  <img alt="License" src="https://img.shields.io/badge/license-MIT-blue">
19
19
  </p>
20
20
 
21
- **Luam** is a typed language for [Multi Theft Auto](https://multitheftauto.com/).
22
- You write `.luam` files with type annotations, classes, enums and template
23
- strings. The compiler checks them and emits readable **Lua 5.1** plus a generated
24
- `meta.xml` — a resource your server can start as-is.
21
+ Write `.luam` files with types, classes, enums and template strings. The
22
+ compiler checks them and emits readable **Lua 5.1** plus a generated `meta.xml` —
23
+ a resource your MTA server can start as-is.
25
24
 
26
- It is *typed Lua*, not TypeScript. Blocks still end with `end` and inequality is
27
- still `~=`, while comments use `#` and `#* ... *#` to avoid colliding with `--` decrement.
25
+ It is *typed Lua*, not TypeScript. Blocks still end with `end`, inequality is
26
+ still `~=`, and comments use `#` and `#* ... *#`.
28
27
 
29
28
  ```lua
30
- local health: number = 100
29
+ enum Target { LUA_51, MTA }
31
30
 
32
- function heal(player: Player, amount: number): void
33
- health += amount
31
+ class Luam {
32
+ version: string
33
+ target: Target = Target.LUA_51
34
+ files: number = 0
34
35
 
35
- outputChatBox(`${getPlayerName(player)} healed to ${health}`, player)
36
- end
36
+ constructor = function (version: string)
37
+ self.version = version
38
+ end
39
+
40
+ compile = function (source: string): string
41
+ self.files += 1
42
+
43
+ return `Luam ${self.version} compiled ${source} to plain Lua 5.1`
44
+ end
45
+ }
46
+
47
+ local luam = new Luam('0.15.6')
48
+
49
+ outputServerLog(luam:compile('src/server/main.luam'))
37
50
  ```
38
51
 
39
52
  Annotations are erased at build time. `dxDrawText` in a server file, a typo in an
40
- MTA function name, a `string` passed where a `number` belongs — all build errors,
41
- before the server ever starts. A build with any error writes nothing.
53
+ MTA function name, a `string` where a `number` belongs — all build errors, before
54
+ the server starts. A build with any error writes nothing.
42
55
 
43
56
  ---
44
57
 
45
58
  ## Install
46
59
 
47
- > Full instructions, including `PATH` troubleshooting:
48
- > **[Installation](https://thigasdevelopment.github.io/luam/en/guide/installation)**
49
- > · [Instalação](https://thigasdevelopment.github.io/luam/pt-br/guide/installation)
50
-
51
- You need [Node.js](https://nodejs.org/) 20 or newer and an
52
- [MTA:SA](https://multitheftauto.com/) 1.5+ server. No Lua toolchain — the
53
- compiler emits Lua text, it never runs it.
54
-
55
- ```bash
56
- node --version # must print v20.x or newer
57
- ```
58
-
59
- ### 1. Install the CLI
60
+ Needs [Node.js](https://nodejs.org/) 20+ and an [MTA:SA](https://multitheftauto.com/)
61
+ 1.5+ server. No Lua toolchain.
60
62
 
61
63
  ```bash
62
64
  npm install --global @thigasdevelopment/luam
63
- ```
64
-
65
- That gives you one command, `luam`. Check it:
66
-
67
- ```bash
68
65
  luam --version
69
66
  ```
70
67
 
71
- | Task | Command |
72
- | --- | --- |
73
- | Install | `npm install --global @thigasdevelopment/luam` |
74
- | Update to the latest | `npm update --global @thigasdevelopment/luam` |
75
- | Install a specific version | `npm install --global @thigasdevelopment/luam@0.1.1` |
76
- | Uninstall | `npm uninstall --global @thigasdevelopment/luam` |
77
- | Run once, without installing | `npx @thigasdevelopment/luam <command>` |
78
-
79
- `npx @thigasdevelopment/luam build` works anywhere and caches the download, which is handy in CI or
80
- on a machine you would rather not install into.
81
-
82
- <details>
83
- <summary><b><code>luam: command not found</code> after installing</b></summary>
84
-
85
- npm put the binary in its global bin directory and that directory is not on your
86
- `PATH`. Find it:
87
-
88
- ```bash
89
- npm config get prefix
90
- ```
91
-
92
- - **Windows** — add that folder itself to your user `PATH`
93
- (*Settings → System → About → Advanced system settings → Environment
94
- Variables*), then open a **new** terminal.
95
- - **macOS / Linux** — add `<prefix>/bin` to your `PATH` in `~/.zshrc` or
96
- `~/.bashrc`, then run `source ~/.zshrc`.
97
-
98
- Nothing to configure if you would rather not: `npx @thigasdevelopment/luam <command>` needs no
99
- `PATH` entry at all.
100
-
101
- </details>
102
-
103
- <details>
104
- <summary><b>Install from source instead</b></summary>
105
-
106
- For contributing, or to run a change that is not released yet. Needs
107
- [pnpm](https://pnpm.io/) 9+.
68
+ Then install the VS Code extension — it runs the same checker as the CLI:
108
69
 
109
70
  ```bash
110
- git clone https://github.com/ThigasDevelopment/luam.git
111
- cd luam
112
- pnpm install
113
- pnpm install:cli
71
+ luam setup # detects your editors and asks before installing
72
+ luam doctor # verifies CLI, editors and extension
114
73
  ```
115
74
 
116
- `install:cli` bundles the compiler into one self-contained file, writes a
117
- publishable manifest next to it, and runs `npm install --global` on the result.
118
- It finishes by running `luam --version` and telling you what to fix if the npm
119
- bin directory is not on your `PATH`.
120
-
121
- </details>
122
-
123
- ### 2. Install the editor extension
124
-
125
- The VS Code extension gives you types, completion and errors while you type —
126
- from the same checker the CLI runs, so the editor and the build never disagree.
127
- Let the CLI detect supported editors and ask before changing each one:
128
-
129
- ```bash
130
- luam setup
131
- ```
132
-
133
- For an unattended development-machine setup, approve every detected editor:
134
-
135
- ```bash
136
- luam setup --yes
137
- ```
138
-
139
- Run `luam doctor` afterward to check the CLI, detected editors, and extension.
140
- See [Editor support](#editor-support) for the compatibility matrix and manual installation.
75
+ > [Installation](https://thigasdevelopment.github.io/luam/en/guide/installation)
76
+ > · [Instalação](https://thigasdevelopment.github.io/luam/pt-br/guide/installation)
77
+ > `PATH` troubleshooting, `npx`, install from source, manual `.vsix`.
141
78
 
142
79
  ---
143
80
 
144
81
  ## Quick start
145
82
 
146
- > Step by step, with a checked example:
147
- > **[Quick start](https://thigasdevelopment.github.io/luam/en/guide/quick-start)**
148
- > · [Início rápido](https://thigasdevelopment.github.io/luam/pt-br/guide/quick-start)
149
-
150
- **1. Scaffold.** `init` writes exactly one file, `.luam.manifest`. No framework, no
151
- example tree, nothing to delete.
83
+ **1. Scaffold.** `init` writes exactly one file, `.luam.manifest`.
152
84
 
153
85
  ```bash
154
86
  mkdir my-resource && cd my-resource
@@ -156,8 +88,7 @@ luam init
156
88
  ```
157
89
 
158
90
  **2. Write some Luam.** Create the source tree yourself — **the folder decides
159
- the environment**: `src/server` is server-side, `src/client` is client-side,
160
- `src/shared` is both.
91
+ the environment**: `src/server`, `src/client`, `src/shared`.
161
92
 
162
93
  ```
163
94
  my-resource/
@@ -168,32 +99,6 @@ my-resource/
168
99
  └── client/hud.luam
169
100
  ```
170
101
 
171
- ```lua
172
- -- src/shared/config.luam
173
- function formatPlayerName(name: string): string
174
- return 'Player: ' .. name
175
- end
176
- ```
177
-
178
- ```lua
179
- -- src/server/main.luam
180
- addEventHandler('onPlayerJoin', root, function()
181
- outputChatBox(formatPlayerName(getPlayerName(source)), root)
182
- end)
183
- ```
184
-
185
- ```lua
186
- -- src/client/hud.luam
187
- local caption: string = `HUD ${RESOURCE_NAME:demo}`
188
-
189
- addEventHandler('onClientRender', root, function()
190
- dxDrawText(caption, 10, 10)
191
- end)
192
- ```
193
-
194
- The compiler already knows `formatPlayerName` is shared, so the server file may
195
- call it — and that `dxDrawText` from `main.luam` would be an error.
196
-
197
102
  **3. Build.**
198
103
 
199
104
  ```bash
@@ -208,15 +113,11 @@ src/client/hud.luam:4:5 error check-environment-api: API "outputChatBox" is serv
208
113
  ```
209
114
 
210
115
  **4. Run it.** Copy `build/my-resource` into
211
- `<MTA Server>/mods/deathmatch/resources/`, then in the server console:
212
-
213
- ```
214
- refresh
215
- start my-resource
216
- ```
116
+ `<MTA Server>/mods/deathmatch/resources/`, then `refresh` and
117
+ `start my-resource` in the server console.
217
118
 
218
119
  **5. Iterate.** Point `.luam.manifest` at your server and let `dev` build, sync,
219
- restart, and stream resource logs on every save:
120
+ restart and stream logs on every save:
220
121
 
221
122
  ```luam
222
123
  name = 'my-resource'
@@ -225,322 +126,80 @@ serverPath = 'C:/MTA Server'
225
126
 
226
127
  ```bash
227
128
  luam dev
129
+ luam dev --start-server # also starts and owns the local MTA process
228
130
  ```
229
131
 
230
- ---
231
-
232
- ## The CLI
233
-
234
- > Every command, option and exit code:
235
- > **[CLI commands](https://thigasdevelopment.github.io/luam/en/tooling/cli)**
236
- > · [Comandos da CLI](https://thigasdevelopment.github.io/luam/pt-br/tooling/cli)
237
-
238
- Project commands read `.luam.manifest` from the current directory or from `--cwd`.
239
- `setup`, `doctor`, and `init` do not require an existing project.
240
-
241
- ### `luam init`
242
-
243
- Scaffolds `.luam.manifest` and stops. The resource name comes from `--name`, or from
244
- the directory you are in.
245
-
246
- ```bash
247
- luam init --name gamemode-race
248
- ```
249
-
250
- An existing `.luam.manifest` is kept and reported — pass `--force` to overwrite it.
251
-
252
- ### `luam setup`
253
-
254
- Detects supported editor commands on `PATH`, asks for consent, and installs the
255
- Luam extension. It tries the editor's marketplace first and falls back to the
256
- official `.vsix` from the GitHub release that matches the CLI version.
257
-
258
- ```bash
259
- luam setup
260
- luam setup --yes
261
- ```
262
-
263
- The command never installs into an editor silently. In CI or another
264
- non-interactive terminal, pass `--yes` explicitly.
265
-
266
- ### `luam doctor`
267
-
268
- Reports the running CLI and Node.js versions, every supported editor detected
269
- on `PATH`, and whether that editor has the Luam extension.
270
-
271
- ```bash
272
- luam doctor
273
- ```
274
-
275
- ### `luam check`
276
-
277
- Compiles everything and prints diagnostics. **Writes nothing.** This is the
278
- command to put in CI and in a pre-commit hook.
279
-
280
- ```bash
281
- luam check
282
- ```
283
-
284
- ```
285
- src/server/main.luam:11:23 error check-type-mismatch: Variable "total" expects "number" but received "string".
286
- Build failed: 1 error, 0 warnings in 4 ms.
287
- ```
288
-
289
- ### `luam build`
290
-
291
- Compiles and writes the bundled production resource into `<outDir>/<name>`, plus
292
- `<outDir>/<name>.luam-map.json` for resolving production error positions. Pass
293
- `--no-bundle` for tree output or `--no-map` to suppress the map.
294
-
295
- ```bash
296
- luam build
297
- ```
298
-
299
- ```
300
- Discovery: done in 1 ms.
301
- Compile: 3 files in 12 ms.
302
- Assembly: done in 0 ms.
303
- Manifest: done in 1 ms.
304
- Write: 7 files in 2 ms.
305
- Build passed: 3 files, 0 errors, 0 warnings in 16 ms.
306
- Wrote 7 files to "build/my-resource".
307
- ```
308
-
309
- A build that reports any error writes nothing, so a resource that worked is
310
- never replaced with partial output.
311
-
312
- ### `luam dev`
313
-
314
- Runs the `ensure` build, server sync, restart, and watch loop while following
315
- `<serverPath>/mods/deathmatch/logs/server.log`. It starts at the end of the file,
316
- so existing history is not printed.
317
-
318
- ```bash
319
- luam dev
320
- ```
321
-
322
- Server records attributed to the active resource and relayed client
323
- `outputDebugString` calls share one stable stream:
324
-
325
- ```
326
- [14:22:07][server][info] Resource started
327
- [14:22:09][client][warn] Missing vehicle model
328
- ```
329
-
330
- The client call still reaches the MTA debug console. `dev` adds a validated,
331
- rate-limited MTA event relay only to the synchronized server resource. `build`
332
- and `ensure` never include these development helpers. Engine output without a
333
- resource identity may appear as plain server output; records attributed to
334
- other resources are ignored.
335
-
336
- ### `luam ensure`
337
-
338
- The loop you leave running while you work. It builds, mirrors the resource into
339
- your MTA server, restarts it, and repeats all of that on every save.
340
-
341
- ```bash
342
- luam ensure
343
- ```
344
-
345
- How much it does depends on what `.luam.manifest` gives it:
346
-
347
- | Configured | What `ensure` does |
348
- | --- | --- |
349
- | nothing | Builds into `<outDir>/<name>` and watches |
350
- | `serverPath` | Also mirrors the resource into the server. You restart it |
351
- | `serverPath` + `transport` | Also refreshes and restarts the resource for you |
352
-
353
- To get the restart, add an `http` transport pointing at a resource on your server
354
- that exports `refreshResources` and `restartResource`:
355
-
356
- ```luam
357
- name = 'my-resource'
358
- serverPath = 'C:/MTA Server'
359
-
360
- transport = {
361
- kind = 'http',
362
- host = '127.0.0.1',
363
- port = 22005,
364
- resource = 'luam-sync',
365
- username = 'luam',
366
- passwordEnv = 'LUAM_MTA_PASSWORD',
367
- }
368
- ```
369
-
370
- ```bash
371
- set LUAM_MTA_PASSWORD=... # Windows
372
- export LUAM_MTA_PASSWORD=... # macOS / Linux
373
- luam ensure
374
- ```
375
-
376
- Use `passwordEnv`, which names an environment variable, rather than an inline
377
- `password` — no log line or diagnostic ever prints the value. MTA's HTTP
378
- interface has no TLS, so keep `host` on `127.0.0.1` and tunnel over SSH instead
379
- of exposing the port.
132
+ > [Quick start](https://thigasdevelopment.github.io/luam/en/guide/quick-start)
133
+ > · [Início rápido](https://thigasdevelopment.github.io/luam/pt-br/guide/quick-start)
380
134
 
381
- Each save rebuilds only the files whose source changed and writes only the files
382
- whose content changed. If the build reports an error, nothing is synced and the
383
- running server keeps the last version that compiled. `Ctrl+C` ends the watch;
384
- `--no-watch` runs the whole cycle exactly once, which is what an editor task or
385
- a deploy script wants.
135
+ ---
386
136
 
387
- ### Options and exit codes
137
+ ## Commands
388
138
 
389
- | Option | Meaning |
139
+ | Command | What it does |
390
140
  | --- | --- |
391
- | `--cwd <path>` | Project directory holding `.luam.manifest`. Defaults to the current directory |
392
- | `--manifest <path>` | Load this file instead of `.luam.manifest` |
393
- | `--name <name>` | Resource name for `init` |
394
- | `--force` | Let `init` overwrite a file that exists |
395
- | `--watch` / `--no-watch` | Keep `ensure` or `dev` watching, or run it once. Both watch by default |
396
- | `--bundle` / `--no-bundle` | Select bundle or tree output for `build` and `ensure`; `dev` always uses tree |
397
- | `--no-map` | Disable source position maps |
398
- | `--map <path>` | Select the resource map for `luam trace` |
399
- | `--offline` | Skip the `min_mta_version` lookup. `LUAM_OFFLINE` does the same |
400
- | `--no-color` | Plain output, no colour or emoji. `NO_COLOR` does the same |
401
- | `-h`, `--help` | Print the usage text |
402
- | `-v`, `--version` | Print the CLI version |
403
-
404
- | Exit code | Meaning |
405
- | --- | --- |
406
- | `0` | The command succeeded |
407
- | `1` | The build reported errors |
408
- | `2` | The command line or the configuration is invalid |
409
-
410
- Progress is painted on stderr and the report goes to stdout, so redirecting
411
- stdout captures the report alone. Output drops all escape sequences when the
412
- stream is not a terminal — a CI log stays readable.
413
-
414
- ### `.luam.manifest`
415
-
416
- Only `name` is required.
417
-
418
- | Field | Default | Meaning |
419
- | --- | --- | --- |
420
- | `name` | required | Names the output folder and the resource `ensure` restarts. MTA reads the resource name from the folder, so it never reaches `meta.xml` |
421
- | `author`, `version`, `description` | unset | `meta.xml` info attributes |
422
- | `compilerOptions` | `strict` on, the rest off | How the checker reads the project: `strict`, `oop`, `noUnusedLocals`, `noUnusedParameters`, `warningsAsErrors` |
423
- | `sources` | `src/<side>/**/*.luam` | Patterns per side. The side that matches a file is its environment, unless a directive overrides it |
424
- | `assets` | `{ }` | `{ from, to }` mappings. Only what a mapping names is copied and declared `<file>` |
425
- | `dependencies` | `{ }` | Resources written as `<include resource="..." />` |
426
- | `engine.minVersion` | `"latest"` | Becomes `min_mta_version`. An explicit version keeps the build network-free |
427
- | `environment` | `.env`, `.env.local` | Which files declare and override the keys behind `env` and `process.env` |
428
- | `outDir` | `"build"` | Receives `<outDir>/<name>` |
429
- | `loadOrder` | `[]` | Source paths pinned ahead of their group in `meta.xml`. An entry matching no file fails the build |
430
- | `output.bundle` | `true` | Default `build` layout; command flags override it |
431
- | `output.map` | `true` | Generate source position maps; only `build` writes one to disk |
432
- | `output.minify` | `true` | Write each generated script on one line during `build`; `dev` and `ensure` never minify |
433
- | `helpers` | `[]` | Runtime helpers to copy even when no feature requires them |
434
- | `serverPath` | unset | MTA server root, for `ensure` |
435
- | `resourcesDir` | `"mods/deathmatch/resources"` | Resource directory relative to `serverPath` |
436
- | `transport` | `{ "kind": "none" }` | How `ensure` restarts the resource |
437
- | `development.logs` | disabled, safe limits | Client relay message length and rate limits used by `dev` |
438
-
439
- Paths must stay inside their base directory — an absolute path or a `..` segment
440
- is rejected. A pattern accepts `*`, `**`, and `?` only. `oop`, `sourceDirs`,
441
- `assetDirs`, and `mta` were removed; each reports `config-removed-field` and
442
- names its replacement.
443
-
444
- Every field, the transport in detail, `.env` handling and declaration files:
445
- **[.luam.manifest](https://thigasdevelopment.github.io/luam/en/tooling/luam-manifest)**
446
- and
447
- [Configuration fields](https://thigasdevelopment.github.io/luam/en/reference/configuration-fields)
448
- · [.luam.manifest](https://thigasdevelopment.github.io/luam/pt-br/tooling/luam-manifest)
449
- · also in [`packages/cli/README.md`](packages/cli/README.md).
141
+ | `luam init` | Scaffolds `.luam.manifest` and stops |
142
+ | `luam check` | Compiles and prints diagnostics. Writes nothing — this is the CI command |
143
+ | `luam build` | Writes the bundled resource into `<outDir>/<name>`, plus a source map |
144
+ | `luam dev` | Build, sync, restart and watch, while following the server log |
145
+ | `luam ensure` | Build, sync and restart on every save |
146
+ | `luam server` | Run an existing local MTA server in the foreground |
147
+ | `luam trace` | Resolves a production error position back to the authored file |
148
+ | `luam setup` | Installs the editor extension |
149
+ | `luam doctor` | Reports CLI, Node.js, detected editors and extension status |
150
+
151
+ Exit codes: `0` success, `1` build errors, `2` invalid command line or
152
+ configuration. Progress goes to stderr and the report to stdout.
153
+
154
+ > [CLI commands](https://thigasdevelopment.github.io/luam/en/tooling/cli)
155
+ > · [Comandos da CLI](https://thigasdevelopment.github.io/luam/pt-br/tooling/cli)
156
+ > every option and exit-code details.
450
157
 
451
158
  ---
452
159
 
453
160
  ## The language
454
161
 
455
- > Every feature, with emitted Lua and the errors it catches:
456
- > **[The language](https://thigasdevelopment.github.io/luam/en/language/)**
457
- > · [A linguagem](https://thigasdevelopment.github.io/luam/pt-br/language/)
458
-
459
- ```lua
460
- local name: string = 'Thigas'
461
- local player: Player? = nil # optional
462
- local id: string | number = 1 # union
463
- local names: string[] = {} # array
464
-
465
- type PlayerId = number # alias
466
-
467
- enum GameState { LOBBY, PLAYING } # GameState.LOBBY is 0
468
-
469
- interface Command { # compile-only, never emitted
470
- name: string
471
- execute(player: Player): void
472
- }
473
-
474
- class VIPPlayer extends Player implements Command {
475
- level: number = 1
476
-
477
- constructor = function (name: string, level: number)
478
- self:super(name)
479
- self.level = level
480
- end
481
- }
482
-
483
- local vip = new VIPPlayer('Thigas', 2)
484
- ```
485
-
486
162
  | Feature | Notes |
487
163
  | --- | --- |
488
164
  | Type annotations | Optionals, unions, arrays, aliases, generics, `fun(string): void` — all erased |
489
- | Classes | `extends`, `implements`, `constructor`, `self:super(...)`, `new`, checked statically |
490
- | Decorators | `@Getter` and `@Setter` generate typed Java-style accessors on fields or whole classes |
165
+ | Classes | `extends`, `implements`, `constructor`, `super(...)`, `new` |
166
+ | Decorators | `@Getter` and `@Setter` generate typed accessors |
491
167
  | Interfaces | Verified by the checker, never reach the generated Lua |
492
168
  | Enums | Zero-based, checked members, erased when unused |
493
169
  | Template strings | `` `Hi ${name:Guest}` `` — scope-checked, with defaults |
494
- | Compound assignment | `+=`, `-=`, `*=`, `/=`, `..=` |
495
- | Increment | `score++` and `score--` as statements, compiled to `score = score + 1` |
496
- | Comments | `# line` and `#* block *#`; write length without a space as `#items` |
497
- | Object extensions | `items.count` → `table.size(items)`, `name.trim`, `ratio.clamp(a, b)` |
170
+ | Operators | `+=`, `-=`, `*=`, `/=`, `..=`, and `score++` / `score--` as statements |
171
+ | Comments | `# line` and `#* block *#`; length without a space is `#items` |
172
+ | Object extensions | `items.count`, `name.trim`, `ratio.clamp(a, b)` |
498
173
  | Multi-return | `local x, y, z = getElementPosition(el)` — typed from the MTA catalog |
499
- | `export` | Erased from the Lua, written into `meta.xml` as `<export function="f" http="false" />` |
500
- | Native libraries | `sleep` plus the `Threads`, `Async` and `Dotenv` classes, injected only when named |
501
- | Native classes | `local tasks = new Async(100)` — same `new` as a project class |
502
- | MTA OOP classes | `Player.getRandom()`, `File.exists(path)`, and callable constructors such as `File(path)` |
503
- | Deployment values | `.env` keys typed and reachable as `env.SERVER_NAME`, server-only |
174
+ | `export` | Erased from the Lua, written into `meta.xml` |
175
+ | Native libraries | `sleep` plus `Threads`, `Async` and `Dotenv`, injected only when named |
176
+ | MTA OOP classes | `Player.getRandom()`, `File.exists(path)`, callable constructors |
177
+ | Deployment values | `.env` keys typed as `env.SERVER_NAME`, server-only |
504
178
  | Strictness | `#!strict` (default), `#!nonstrict`, `#!nocheck` per file |
505
179
 
506
180
  `class`, `constructor`, `declare`, `enum`, `export`, `extends`, `implements`,
507
- `interface`, `new` and `type` are **reserved**, on top of the 21 Lua 5.1
508
- keywords. Existing Lua that uses one as an identifier needs a rename — but a
509
- property name still works (`config.type`), and `type(value)` keeps working
510
- because `type` stays callable. `fun` is the one term that stays contextual.
511
-
512
- Reach for `#!nocheck` when porting existing Lua: rename to `.luam` and the build
513
- passes while you annotate module by module.
181
+ `interface`, `new` and `type` are **reserved** on top of the Lua 5.1 keywords.
182
+ Property names still work (`config.type`), and `type(value)` keeps working.
183
+ Porting existing Lua? Rename to `.luam`, add `#!nocheck`, and annotate module by
184
+ module.
514
185
 
515
186
  ### Environments
516
187
 
517
188
  Every file is `server`, `client` or `shared` — from its folder, or from a `#!`
518
- directive. That decides which MTA APIs resolve.
519
-
520
- ```lua
521
- #!client
522
-
523
- dxDrawText('hud', 10, 10) # ok
524
- outputChatBox('hi', player) # error: server API in a client file
525
- ```
526
-
527
- `server` and `client` files may use `shared` declarations; `shared` may use only
528
- `shared`; `server` and `client` never see each other. Events are scoped the same
529
- way. A name the catalog does not know stays `any`, so a missing API never blocks
530
- a build.
189
+ directive. That decides which MTA APIs resolve: `dxDrawText` in a client file is
190
+ fine, `outputChatBox` in the same file is a build error.
531
191
 
532
- The catalog ships **1294 MTA declarations**, **203 events**, **57 element types**
533
- and the Lua standard library, generated from the MTA wiki — plus the OOP surface
534
- (**57 classes, 652 methods, 118 static methods, 46 constructors**) behind
535
- `"oop": true`.
192
+ `server` and `client` may use `shared` declarations; `shared` may use only
193
+ `shared`; `server` and `client` never see each other. A name the catalog does
194
+ not know stays `any`, so a missing API never blocks a build.
536
195
 
537
- `File(path)` opens an existing file read/write and creates it when missing.
538
- Use `File.new(path)` only for destructive creation because it truncates an
539
- existing file. Use `fileOpen(path, true)` when read-only access is required.
196
+ > [The language](https://thigasdevelopment.github.io/luam/en/language/)
197
+ > · [A linguagem](https://thigasdevelopment.github.io/luam/pt-br/language/)
198
+ > every feature, with the emitted Lua and the errors it catches.
540
199
 
541
200
  ---
542
201
 
543
- ## What you get out
202
+ ## Output
544
203
 
545
204
  ```
546
205
  build/
@@ -556,138 +215,69 @@ build/
556
215
  └── client.lua
557
216
  ```
558
217
 
559
- `build` ships at most one bundle per non-empty environment. `config.lua`, `.env`,
560
- and assets remain unbundled at their stable paths, and the map remains outside
561
- the resource. `ensure` defaults to a mirrored tree and `dev` always uses one.
562
- Use `luam trace src/server.lua:42` with the matching map to recover the authored
563
- file, line, and symbol. See [output layouts and source maps](https://thigasdevelopment.github.io/luam/en/reference/output-layouts).
218
+ `build` ships at most one bundle per non-empty environment; `config.lua`, `.env`
219
+ and assets stay at their own paths, and the map stays outside the resource.
220
+ `ensure` defaults to a mirrored tree and `dev` always uses one.
564
221
 
565
- `min_mta_version` is resolved from the latest MTA release and cached;
566
- with no network and no cache it is omitted with a warning, and the build still
567
- succeeds.
222
+ > [Output layouts and source maps](https://thigasdevelopment.github.io/luam/en/reference/output-layouts)
568
223
 
569
224
  ---
570
225
 
571
- ## Editor support
572
-
573
- > Compatibility matrix, manual `.vsix` install, settings:
574
- > **[Editors](https://thigasdevelopment.github.io/luam/en/tooling/editors)**
575
- > · [Editores](https://thigasdevelopment.github.io/luam/pt-br/tooling/editors)
576
-
577
- The **Luam** extension for VS Code starts a language server built on the same
578
- frontend the CLI uses, so the editor and the build never disagree about a file.
579
-
580
- | You get | Details |
581
- | --- | --- |
582
- | Syntax highlighting | `.luam` files, including type annotations and template strings |
583
- | Diagnostics | On open and on every keystroke, cleared when you fix the file |
584
- | Completion | Scope symbols, workspace globals, MTA APIs scoped to the file's environment, keywords |
585
- | Member completion | `.` completes fields and static methods; `:` completes instance methods, including inherited MTA members |
586
- | Hover | Declared or inferred type, function signature, and the environment of an MTA API |
587
- | Navigation | Go to definition, find references, rename — across files for globals |
588
-
589
- Completion is scoped exactly like the checker: `dxDrawText` never appears in a
590
- server file, `kickPlayer` never appears in a client file.
591
-
592
- ### Installing it
226
+ ## Configuration
593
227
 
594
- **Through the CLI (recommended).** The command detects all supported editors
595
- whose launchers are on `PATH` and asks before installing:
228
+ `.luam.manifest` only `name` is required.
596
229
 
597
- ```bash
598
- luam setup
599
- ```
600
-
601
- | Editor | Launcher detected | Automatic installation | Distribution path |
602
- | --- | --- | --- | --- |
603
- | Visual Studio Code | `code` | Yes | Marketplace, then release `.vsix` fallback |
604
- | Visual Studio Code Insiders | `code-insiders` | Yes | Marketplace, then release `.vsix` fallback |
605
- | Cursor | `cursor` | Yes | Editor marketplace, then release `.vsix` fallback |
606
- | VSCodium | `codium` | Yes | Open VSX when available, then release `.vsix` fallback |
607
- | Windsurf | `windsurf` | Yes | Editor marketplace, then release `.vsix` fallback |
608
-
609
- Other VS Code-compatible forks can usually install the release `.vsix`
610
- manually, but `luam setup` does not claim support until their launcher and
611
- extension APIs are stable. JetBrains IDEs need a separate plugin and are not
612
- supported by this VS Code extension. Neovim, Zed, and Sublime Text need their
613
- own LSP adapter or extension and are not currently supported.
614
-
615
- **From a release.** Download `luam-<version>.vsix` from the
616
- [Releases page](https://github.com/ThigasDevelopment/luam/releases), then use
617
- the launcher for your editor:
618
-
619
- ```bash
620
- code --install-extension luam-0.1.1.vsix
621
- cursor --install-extension luam-0.1.1.vsix
622
- codium --install-extension luam-0.1.1.vsix
623
- windsurf --install-extension luam-0.1.1.vsix
624
- ```
625
-
626
- In a compatible editor, you can also open **Extensions**, choose **Install from
627
- VSIX**, and select the downloaded file. Reload the window when prompted.
628
-
629
- **From source.** Build the VSIX yourself:
630
-
631
- ```bash
632
- git clone https://github.com/ThigasDevelopment/luam.git
633
- cd luam
634
- pnpm install
635
- pnpm --filter luam bundle
636
- npx --yes @vscode/vsce package --no-dependencies --skip-license --out luam.vsix
637
- code --install-extension luam.vsix
638
- ```
639
-
640
- **To hack on the extension**, skip packaging and launch a development host
641
- instead — it reloads on rebuild:
642
-
643
- ```bash
644
- pnpm --filter luam bundle
645
- code --extensionDevelopmentPath=packages/vscode
230
+ ```luam
231
+ name = 'my-resource'
232
+ serverPath = 'C:/MTA Server'
646
233
  ```
647
234
 
648
- The extension activates when the workspace holds a `.luam.manifest` or any `.luam`
649
- file, so open your resource folder as the workspace root.
235
+ Optional fields cover `meta.xml` info, `compiler`, `sources`, `assets`,
236
+ `dependencies`, `engine.minVersion`, `environment`, `outDir`, `loadOrder`,
237
+ `output`, `helpers`, `resourcesDir`, `development.logs` and
238
+ `development.server.executable`.
650
239
 
651
- ### Commands and settings
240
+ > [.luam.manifest](https://thigasdevelopment.github.io/luam/en/tooling/luam-manifest)
241
+ > and [Configuration fields](https://thigasdevelopment.github.io/luam/en/reference/configuration-fields)
242
+ > · [.luam.manifest](https://thigasdevelopment.github.io/luam/pt-br/tooling/luam-manifest)
652
243
 
653
- | Command | Shortcut | What it does |
654
- | --- | --- | --- |
655
- | **Luam: Ensure Resource** | `Ctrl+Alt+E` (`Cmd+Alt+E`) | Runs `luam ensure` in a terminal for the current project |
656
- | **Luam: Restart Language Server** | — | Restarts the server when it gets confused |
244
+ ---
657
245
 
658
- | Setting | Default | Meaning |
659
- | --- | --- | --- |
660
- | `luam.cliPath` | `"luam"` | Command used to run the CLI. Point it at a bundle to test an unreleased build |
661
- | `luam.ensureWatch` | `true` | Pass `--watch` when the ensure command runs |
662
- | `luam.trace.server` | `"off"` | Trace the LSP traffic. Set to `"verbose"` when reporting a bug |
246
+ ## Editor support
663
247
 
664
- ### Other editors
248
+ The **Luam** VS Code extension runs a language server built on the same frontend
249
+ as the CLI, so the editor and the build never disagree: syntax highlighting,
250
+ diagnostics on every keystroke, scoped completion, hover types, go to
251
+ definition, find references and rename.
665
252
 
666
- The language server is editor-agnostic. Bundle it and launch it with `--stdio`
667
- from any LSP client:
253
+ Supported and auto-installed by `luam setup`: VS Code, VS Code Insiders, Cursor,
254
+ VSCodium and Windsurf. The language server itself is editor-agnostic and speaks
255
+ `--stdio` to any LSP client.
668
256
 
669
- ```bash
670
- pnpm --filter @luam/lsp bundle # emits packages/lsp/dist/luam-lsp.mjs
671
- node packages/lsp/dist/luam-lsp.mjs --stdio
672
- ```
257
+ > [Editors](https://thigasdevelopment.github.io/luam/en/tooling/editors)
258
+ > · [Editores](https://thigasdevelopment.github.io/luam/pt-br/tooling/editors)
259
+ > — compatibility matrix, manual `.vsix` install, commands and settings.
673
260
 
674
261
  ---
675
262
 
676
263
  ## Known limitations
677
264
 
678
- > With the workaround for each:
679
- > **[Limitations](https://thigasdevelopment.github.io/luam/en/reference/limitations)**
680
- > · [Limitações](https://thigasdevelopment.github.io/luam/pt-br/reference/limitations)
681
-
682
- - **No type narrowing.** `if value ~= nil then` does not refine `string?`.
683
- - **Declaration order matters for classes within a file.** `extends` and `new`
684
- resolve against classes declared earlier in the same file.
685
- - **The MTA catalog can lag a release.** It comes from a pinned snapshot; a newer
686
- function stays `any` rather than erroring.
265
+ - **Narrowing reaches names, not fields.** `if value ~= nil then` refines a local;
266
+ `self.value` keeps its declared type however you test it.
267
+ - **A class is a type everywhere, a value from its declaration** — `extends` may
268
+ name a parent written further down, a top-level `new` may not.
269
+ - **The MTA catalog can lag a release** a newer function stays `any`.
687
270
  - **No static members, declared metamethods, or generic classes.**
688
- - **The editor does not re-check an open file when another one changes.**
689
- Cross-module violations surface in `luam check`.
271
+ - **The editor re-checks by declaration** a declaration change re-analyzes every
272
+ file that can see it, an edit inside a function body only its own file.
690
273
  - **An export is named, never verified** against the side that calls it.
274
+ - **Type annotations are erased**, so validate anything a client can send.
275
+
276
+ > [Limitations](https://thigasdevelopment.github.io/luam/en/reference/limitations)
277
+ > · [Limitações](https://thigasdevelopment.github.io/luam/pt-br/reference/limitations)
278
+ > — each one labelled planned, design boundary, upstream or platform constraint,
279
+ > with the workaround. The decisions behind the boundaries are recorded in
280
+ > [`docs/adr`](docs/adr).
691
281
 
692
282
  ---
693
283
 
@@ -698,39 +288,25 @@ The repo is a pnpm workspace: `compiler`, `cli`, `lsp`, `vscode`, `runtime`,
698
288
 
699
289
  ```bash
700
290
  pnpm install
701
- pnpm typecheck # strict TypeScript across every package
702
- pnpm test # 769 tests
291
+ pnpm typecheck
292
+ pnpm test
703
293
  pnpm build
704
294
  ```
705
295
 
706
296
  Branch from `develop`, add a fixture and a snapshot for new language behaviour,
707
- and run `pnpm typecheck && pnpm test` before opening a pull request. The house
708
- style is TypeScript only, strict, no `any`, no comments inside code, 4-space
709
- indentation, single quotes, kebab-case file names, path aliases instead of `../`
710
- imports, no barrel files, and everything written in English.
711
-
712
- Each package documents itself: [`cli`](packages/cli/README.md),
713
- [`lsp`](packages/lsp/README.md), [`mta-types`](packages/mta-types/README.md),
714
- [`vscode`](packages/vscode/README.md) and
715
- [`template`](packages/template/README.md). Released milestones and their changes
716
- are in the [changelog](CHANGELOG.md).
717
-
718
- ### The manual
719
-
720
- The user-facing manual lives in [`docs/`](docs/) and is published to
721
- [thigasdevelopment.github.io/luam](https://thigasdevelopment.github.io/luam/).
722
-
723
- ```bash
724
- pnpm docs:dev # local preview with hot reload
725
- pnpm docs:verify # locale parity, snippet checks, and a full build
726
- ```
727
-
728
- English is the source locale and pt-BR is translated from it; every page exists in
729
- both, and CI fails when one is missing. Code samples are real files under
730
- `docs/snippets/`, verified with `luam check` on every documentation build, and
731
- rendered into both locales from the same source — so a sample cannot drift. See
732
- the [documentation changelog](https://thigasdevelopment.github.io/luam/en/changelog)
733
- for the conventions.
297
+ and run `pnpm typecheck && pnpm test` before opening a pull request. House style:
298
+ TypeScript only, strict, no `any`, no comments inside code, 4-space indentation,
299
+ single quotes, kebab-case file names, path aliases instead of `../` imports, no
300
+ barrel files, everything in English.
301
+
302
+ The manual lives in [`docs/`](docs/) — `pnpm docs:dev` to preview,
303
+ `pnpm docs:verify` before pushing. English is the source locale and pt-BR is
304
+ translated from it; CI fails when a page is missing from one.
305
+
306
+ Per-package docs: [`cli`](packages/cli/README.md), [`lsp`](packages/lsp/README.md),
307
+ [`mta-types`](packages/mta-types/README.md), [`vscode`](packages/vscode/README.md),
308
+ [`template`](packages/template/README.md). Releases are in the
309
+ [changelog](CHANGELOG.md).
734
310
 
735
311
  ---
736
312