nanos-lint 2.8.2 → 3.0.1
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 +75 -3
- package/action.yml +16 -7
- package/dist/{cli-BTHx4yp_.js → cli-B9EpAClV.js} +3612 -2518
- package/dist/cli-B9EpAClV.js.map +1 -0
- package/dist/cli-dxsaVVVq.d.ts.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +154 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/package.json +3 -3
- package/templates/.luarc.json +7 -0
- package/dist/cli-BTHx4yp_.js.map +0 -1
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ A dedicated, fast linter and type-checker for **[nanos world](https://nanos-worl
|
|
|
13
13
|
|
|
14
14
|
## Features
|
|
15
15
|
|
|
16
|
+
- **Realm-aware diagnostics**: `Server/`, `Client/` and `Shared/` are checked against their real execution context, so cross-realm API misuse and client/server global leakage fail the build instead of crashing at runtime.
|
|
16
17
|
- **Accurate nanos world Type Checking**: Bundles verified nanos world API annotations (Lua 5.4.9).
|
|
17
18
|
- **Zero-Install Local CLI**: Run directly via `npx nanos-lint [path]` without installing anything.
|
|
18
19
|
- **Native GitHub Action**: Use `vugi99/nanos-lint` directly in CI workflows with inline GitHub PR annotations.
|
|
@@ -95,7 +96,7 @@ jobs:
|
|
|
95
96
|
uses: actions/checkout@v7
|
|
96
97
|
|
|
97
98
|
- name: Lint nanos world Lua scripts
|
|
98
|
-
uses: vugi99/nanos-lint@
|
|
99
|
+
uses: vugi99/nanos-lint@v3
|
|
99
100
|
with:
|
|
100
101
|
path: "."
|
|
101
102
|
checklevel: "Warning"
|
|
@@ -112,7 +113,8 @@ jobs:
|
|
|
112
113
|
| `ignore` | Files or directories to ignore (supports glob patterns, newline or comma separated) | `""` |
|
|
113
114
|
| `luals-version` | Version of `lua-language-server` to use | `latest` |
|
|
114
115
|
| `fail-on-error` | Fail the workflow step if diagnostics are found | `true` |
|
|
115
|
-
| `
|
|
116
|
+
| `log-level` | Logging level (`error`, `warn`, `info`, `debug`, `silent`) | `warn` |
|
|
117
|
+
| `realm` | Execution realm to check (`all`, `client`, `server`, `shared`) | `all` |
|
|
116
118
|
| `cache` | Whether to cache the LuaLS binary and annotations across workflow runs | `true` |
|
|
117
119
|
|
|
118
120
|
When caching is enabled, the cache key rolls over each ISO week, so a freshly downloaded LuaLS binary is actually persisted under the new week's key; in the meantime the previous week's entry is restored from the cache.
|
|
@@ -151,7 +153,7 @@ OPTIONS:
|
|
|
151
153
|
--github Output in GitHub Actions format (shortcut for --format=github)
|
|
152
154
|
--luals-version=<ver> Version of LuaLS to use (default: latest, falling back to 3.19.1 when offline)
|
|
153
155
|
--no-fail Do not exit with code 1 if diagnostics are found
|
|
154
|
-
--
|
|
156
|
+
--realm <realm> Execution realm to check: all, client, server, shared (default: all)
|
|
155
157
|
-f, --force (init command only) Overwrite existing .luarc.json
|
|
156
158
|
```
|
|
157
159
|
|
|
@@ -194,6 +196,76 @@ npx nanos-lint init
|
|
|
194
196
|
npx nanos-lint init --force
|
|
195
197
|
```
|
|
196
198
|
|
|
199
|
+
### Realm Mapping (`nanos.realms`)
|
|
200
|
+
|
|
201
|
+
nanos world runs two isolated Lua VMs: the server executes `Server/**` + `Shared/**`, the client executes `Client/**` + `Shared/**`. `nanos-lint` mirrors that split and lets you describe a non-standard layout in `.luarc.json`:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"nanos": {
|
|
206
|
+
"realms": {
|
|
207
|
+
"src/server/**": "server",
|
|
208
|
+
"src/client/**": "client",
|
|
209
|
+
"common/**": "shared"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
| Realm value | Meaning |
|
|
216
|
+
| :---------------------- | :-------------------------------------------------------------------------------------------------------------- |
|
|
217
|
+
| `"server"` | Checked with the server context: client-only APIs and `Client/**` globals do not exist. |
|
|
218
|
+
| `"client"` | Checked with the client context: server-only APIs and `Server/**` globals do not exist. |
|
|
219
|
+
| `"shared"` / `"global"` | Checked with the complete context, because a shared script may guard side-specific calls behind runtime checks. |
|
|
220
|
+
|
|
221
|
+
- Omitting `nanos.realms` falls back to the conventional `Server/**`, `Client/**`, `Shared/**` layout, and realm passes only run when at least one of those patterns matches a checked Lua file.
|
|
222
|
+
- `"nanos": { "realms": {} }` disables realm checking and restores a single standard pass.
|
|
223
|
+
- When several entries match the same file, the last matching entry wins.
|
|
224
|
+
- Files matched by no entry (a root `main.lua`, for example) are checked with the complete context.
|
|
225
|
+
|
|
226
|
+
The `nanos` key is nanos-lint specific and ignored by LuaLS, so the same `.luarc.json` keeps working in the editor.
|
|
227
|
+
|
|
228
|
+
### File Counting and Glob Semantics
|
|
229
|
+
|
|
230
|
+
The `N files checked` figure is produced by matching `workspace.ignoreDir` and `files.exclude` with the bundled `glob` engine. The v3.0.0 contract is:
|
|
231
|
+
|
|
232
|
+
- **Trailing slashes and `./` prefixes** are normalized (`vendor/` behaves like `vendor`), and `\` separators are converted to `/`.
|
|
233
|
+
- **Wildcards** follow standard glob semantics (`*`, `**`, `?`, `[0-9]`, `{a,b}`), including inside `workspace.ignoreDir`.
|
|
234
|
+
- **Absolute entries are rejected** (with a warning). LuaLS matches patterns relative to the workspace root, and `glob` anchors absolute patterns inconsistently across platforms, so one `.luarc.json` stays portable by not supporting them.
|
|
235
|
+
- **Negation prefixes (`!pattern`) are rejected** (with a warning). LuaLS uses a gitignore-style matcher without negation support, so honoring `!` here would count files LuaLS never checks.
|
|
236
|
+
- **Over-budget patterns** (excessive wildcards or brace alternatives) are skipped with a warning instead of risking a slow, backtracking-heavy match. Skipping can only over-count, never hide a file.
|
|
237
|
+
- **Symlinks are never followed**: symlinked `.lua` files are not counted and symlinked directories are not traversed.
|
|
238
|
+
- A `workspace.ignoreDir` list in your `.luarc.json` **replaces** the built-in defaults for that file, mirroring LuaLS. The configuration handed to LuaLS is always merged with nanos-lint's defaults, so `.git`, `.vscode`, `.nanos-lint` and `node_modules` stay ignored during a check.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Realm-Aware Checking
|
|
243
|
+
|
|
244
|
+
nanos world loads a package into two isolated Lua VMs: the **server** executes `Server/**` plus `Shared/**`, and the **client** executes `Client/**` plus `Shared/**`. `nanos-lint` mirrors that split so a `Client/` script can no longer call `Server.ChangeMap()` unnoticed, and a global defined in `Client/` no longer satisfies a `Server/` script.
|
|
245
|
+
|
|
246
|
+
`nanos-lint check <path>` detects the conventional layout automatically and runs one LuaLS pass per realm (see [Realm Mapping](#realm-mapping-nanosrealms) to describe a custom layout):
|
|
247
|
+
|
|
248
|
+
| Pass | Files reported | Context |
|
|
249
|
+
| :--------- | :------------------------- | :--------------------------------------------------------------------------------------------------------------------- |
|
|
250
|
+
| **server** | `Server/**` | Server annotations only; `Client/**` is excluded from the analysis. |
|
|
251
|
+
| **client** | `Client/**` | Client annotations only; `Server/**` is excluded from the analysis. |
|
|
252
|
+
| **shared** | `Shared/**` and root files | The complete annotation set, because a shared script may legitimately call a side-specific API behind a runtime check. |
|
|
253
|
+
|
|
254
|
+
Only the annotations that belong to a realm are loaded, so misuse is reported as `undefined-global` (for side-only classes such as `Client`, `Server`, `Database` or `WebUI`) or as `undefined-field` (for realm-specific members of classes that exist on both sides, such as `Character:SetTeam()` on the client).
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
nanos-lint check . # every detected realm
|
|
258
|
+
nanos-lint check . --realm server # server files + shared files
|
|
259
|
+
nanos-lint check . --realm client # client files + shared files
|
|
260
|
+
nanos-lint check . --realm shared # shared files only, with the complete context
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Deliberate limits:
|
|
264
|
+
|
|
265
|
+
- **Runtime guards are not analyzed.** `Shared/**` is checked with the complete context, so a guarded `Server.ChangeMap()` inside a `Package.IsUnloading()`-style branch is accepted, and so is an unguarded one. Real nanos world packages gate calls in too many ways for static detection to be reliable.
|
|
266
|
+
- **`Package.Require` keeps resolving across realms**, because `runtime.path` keeps `?.lua`, `Shared/?.lua`, `Client/?.lua` and `Server/?.lua` in every pass. A shared file may require a realm-specific module behind a guard.
|
|
267
|
+
- **Realm checking only activates when a configured pattern matches at least one checked Lua file**, so non-package repositories keep running a single standard pass. `"nanos": { "realms": {} }` disables it explicitly.
|
|
268
|
+
|
|
197
269
|
---
|
|
198
270
|
|
|
199
271
|
## Pre-packaged Release Distributions (Offline / CD)
|
package/action.yml
CHANGED
|
@@ -30,10 +30,14 @@ inputs:
|
|
|
30
30
|
description: "Whether to fail the action step if diagnostic errors/warnings are found"
|
|
31
31
|
required: false
|
|
32
32
|
default: "true"
|
|
33
|
-
|
|
34
|
-
description: "
|
|
33
|
+
log-level:
|
|
34
|
+
description: "Logging level: error, warn, info, debug, silent"
|
|
35
35
|
required: false
|
|
36
|
-
default: "
|
|
36
|
+
default: "warn"
|
|
37
|
+
realm:
|
|
38
|
+
description: "Execution realm to check: all, client, server, shared"
|
|
39
|
+
required: false
|
|
40
|
+
default: "all"
|
|
37
41
|
ignore:
|
|
38
42
|
description: "Files or directories to ignore (supports glob patterns, multiple entries can be newline or comma separated)"
|
|
39
43
|
required: false
|
|
@@ -80,7 +84,8 @@ runs:
|
|
|
80
84
|
INPUT_ANNOTATIONS: ${{ inputs.annotations }}
|
|
81
85
|
INPUT_LUALS_VERSION: ${{ inputs.luals-version }}
|
|
82
86
|
INPUT_FAIL_ON_ERROR: ${{ inputs.fail-on-error }}
|
|
83
|
-
|
|
87
|
+
INPUT_LOG_LEVEL: ${{ inputs.log-level }}
|
|
88
|
+
INPUT_REALM: ${{ inputs.realm }}
|
|
84
89
|
INPUT_IGNORE: ${{ inputs.ignore }}
|
|
85
90
|
ACTION_PATH: ${{ github.action_path }}
|
|
86
91
|
run: |
|
|
@@ -107,8 +112,12 @@ runs:
|
|
|
107
112
|
ARGS+=("--no-fail")
|
|
108
113
|
fi
|
|
109
114
|
|
|
110
|
-
if [ "$
|
|
111
|
-
ARGS+=("--
|
|
115
|
+
if [ -n "$INPUT_LOG_LEVEL" ]; then
|
|
116
|
+
ARGS+=("--log-level=$INPUT_LOG_LEVEL")
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
if [ -n "$INPUT_REALM" ]; then
|
|
120
|
+
ARGS+=("--realm=$INPUT_REALM")
|
|
112
121
|
fi
|
|
113
122
|
|
|
114
123
|
# dist/ is gitignored, so `uses: vugi99/nanos-lint@<ref>` consumers always
|
|
@@ -118,5 +127,5 @@ runs:
|
|
|
118
127
|
else
|
|
119
128
|
# Exact version: a range could run a different release than the pinned
|
|
120
129
|
# tag. Bump together with "version" in package.json.
|
|
121
|
-
npx --yes nanos-lint@
|
|
130
|
+
npx --yes nanos-lint@3.0.1 "${ARGS[@]}"
|
|
122
131
|
fi
|